loadChildren is deprecated in angular8 - lazy-loading

I just noticed that Angular 8 (which will be released soon), has deprecated "string-typed router loadChildren". (ticket)
Do I understand correctly that they are refering to ...
const routes = [
{
path: 'production',
loadChildren: './production/production.module#ProductionModule' // <<--this
}],
To migrate to Angular 8, what is the solution ?
In the ticket they are refering to "dynamic imports". Am I correct that this refers to the following proposal:
let module = await import('/modules/my-module.js');
Could somebody give a preview of what the routing file should actually look like if we wanted to use lazy loading in the future ?

As loadChildren:string is deprecated in angular 8 Change your loadChildren declarations
From
loadChildren: './production/production.module#ProductionModule'
To
loadChildren: () => import('./production/production.module').then(m => m.ProductionModule)
For more you can ref angular official git link and commit

Apparently, it's not the entire "loadChildren" : ... which is deprecated. It just will no longer accept strings. Instead you have to specify a function now.
The documentation is already available here.
It comes down to:
const routes = [
{
path: 'lazy',
loadChildren : () => import('./production/production.module').then(m => m.ProductionModule),
}
];

Related

Call context in nuxt not working in v-bind

I have question related to using context or prototype in Nuxt
I create a constant for 'modal' name like this:
export default Object.freeze({
MODAL_SHOWPRO: "MODAL_SHOWPRO",
})
I also created constant.js in plugin folder and already added to nuxt config.
import modals from '#/constants/modal';
export default ({ app }, inject) => {
inject('modalName', modals)
}
In component I can't call value from v-bind, it said : undefined MODAL_SHOWPRO
<Popup :id="$modalName.MODAL_SHOWPRO" />
but I can call it from $emit function something like this:
#click="$nuxt.$emit('showModal', {id: $modalName.MODAL_SHOWPRO})"
Can you let me know why and how to fix it?
Notice: It will work if:
I make data
{
modal: ''
}
and add to created:
async created() {
this.modalName = await this.$modalName
}
Nuxt is a meta-framework aimed at providing an universal app (server then client side). So, you need to think about both server and client.
In your code, you specified ssr: false, this is outdated and should rather be mode: 'client'. But setting so is still false because it means that the ENUM will not be available on the server (hence the error).
Setting it like this is more appropriate (regarding the nature of the plugin) and also fixes the issue
plugins: ['~/plugins/constant.js'],
More on Nuxt plugins: https://nuxtjs.org/docs/directory-structure/plugins#plugins-directory

nestjsx-automapper profiles not found in nestjs test modules

Im trying to make unit testing for some features in my NestJS API.
I make use of nestjsx-automapper. The exception happens only while testing any service that uses mappings. I use #nestjs/testing and jest.
I have managed to replicate the error in this test:
describe('UserController', () => {
let userServiceInterface: UserServiceInterface;
beforeEach(async () => {
const app: TestingModule = await Test.createTestingModule({
imports: [AutomapperModule.withMapper('user')],
providers: [
{
provide: 'UserServiceInterface',
useClass: UserService,
},
],
}).compile();
userServiceInterface = app.get<UserServiceInterface>(
'UserServiceInterface',
);
});
describe('find', () => {
it(`should return user with name 'pipo'`, () => {
const user = userServiceInterface.find('pipo');
expect(user.username).toBe('pipo');
});
});
});
I've been looking for different ways to configure profiles, but importing them is the only way I've found.
Thanks in advance.
I figured out how nestjsx-automapper load profiles.
As you can't provide profiles in modules, you depend on that the application runs the profiles first, and it is handled by AutomapperModule from nestjsx-automapper.
I don't know why nest Modules load AutomapperModule and consequently the profiles, but Test Modules doesn't, I will have to work more with nest to understand it.
To tell Test Modules to load AutomapperModule (as they don't by default) on init, use:
moduleRef.get(AutomapperModule).onModuleInit();

Lazy Loading Issue | Spartacus 2.0.0

I am trying to implement lazy loading feature using Spartacus 2.0 but facing below issues:
Templates are not getting visible after it is loaded at very first
time.
Components are getting visible when we again come back to same page.
Also some components are getting visible only after I resize the
screen once after page is loaded.
We are using below strategy mentioned at below location for component lazy loading
https://sap.github.io/spartacus-docs/lazy-loading-guide/
Here is code snippet for one of the module file:
Module1,
Module2,
ConfigModule.withConfig({
cmsComponents: {
ComponentABC: {
component: () =>
import('./xyz.component').then(
(m) => m.xyz
)
}
}
}),
storefrontModule
],
Please suggest for possible solutions.
I think it should looks like:
ConfigModule.withConfig({
cmsComponents: {
ABCComponent: {
component: ABCComponent,
},
XYZComponent: {
component: () => import('./xyz.component').then(m => m.XYZComponent)
}
}
}),
For using lazy loading with Spartacus version 2.0, the 2.x lazy loading guide may be more appropriate: https://sap.github.io/spartacus-docs/2.x/lazy-loading-guide/

Nuxt.js env Property, understanding and how to use it?

following https://nuxtjs.org/api/configuration-env
I have been trying to set up my apiUrl in nuxt.config.js once for the whole project, like:
export default {
env: {
apiUrl: process.env.MY_REMOTE_CMS_API_URL || 'http://localhost:1337'
}
}
adding this in nuxt.config.js, I'd expect (and would like) to have apiUrl accessible everywhere in the project.
In particular, it is needed for the 3 following cases:
with axios, to generate static pages from dynamic urls (in nuxt.config.js)
generate: {
routes: function () {
return axios.get(apiUrl + '/posts')
.then((res) => {
return res.data.filter(page => {
return page.publish === true;
}).map(page => {
return {
route: '/news/' + page.slug
}
})
})
}
},
with apollo, to get data via graphql (in nuxt.config.js)
apollo: {
clientConfigs: {
default: {
httpEndpoint: apiUrl + '/graphql'
}
}
},
in every layout, page and components, as the base url of media:
<img :src="apiUrl + item.image.url" />
As you might see, only thing I need is to 'print' the actual base url of the cms.
I have also tried to access it with process.env.apiUrl, with no success.
The only way I was able to make it has been to create an extra plugin/apiUrl.js file, which injects the api url, and seems wrong to me as I am now setting the apiUrl twice in my project.
I asked this question in the past, but in a way less clear way. I was suggested to use dotenv, but from the docs it looks like adding an additional layer of complication that might not be necessary for a simpler setup.
Thanks.
I think dotenv module really is what you need.
This is my setup:
Project root has a .env file that contains
BASE_URL=https://www.myapi.com
require('dotenv').config() at top of nuxt.config.js
#nuxtjs/dotenv installed and added to buildModules of nuxt.config.js
env: { BASE_URL: process.env.BASE_URL} added to nuxt.config.js
axios: { baseURL: process.env.BASE_URL } added to nuxt.config.js (optional)
You should have access to your .env throughout the project. (process.env.BASE_URL)
I haven't used apollo, but you should be able to set the apollo endpoint with process.env.BASE_URL + '/graphql'
As of Nuxt 2.13, #nuxtjs/dotenv is not required anymore. Read here
The concept that I was missing is that you set up the same named variable in your server / pipeline, so that you have your (always local / never pushed) .env file and a same name variable remotely, not added to your repo (where the value can be the same or different)

How to cache .mp4 files in Safari with workbox-webpack-plugin?

I'm having exactly the same issue reported at https://github.com/GoogleChrome/workbox/issues/1663 which describes an issue that occurs exclusively in Safari where mp4 videos are not rendered after being cached by the service worker.
I'm using workbox-webpack-plugin, so the instructions provided in the comment https://github.com/GoogleChrome/workbox/issues/1663#issuecomment-448755945 will not work in my case. I'm not being able to require workbox-range-requests plugin in my webpack config file and pass it to the runtime caching options because I believe this package is intended for browser usage only. My workbox config is precaching .mp4 assets and uses a network first strategy for runtime caching.
How can I setup workbox-range-requests with workbox-webpack-plugin?
EDIT: Following Jeff's answer below, I've adjusted my webpack config to the following:
new WorkboxPlugin.InjectManifest({
swSrc: serviceWorkerSrcPath,
swDest: serviceWorkerBuildPath,
importsDirectory: 'sw',
})
The build produces the following service worker:
importScripts("/_build/sw/precache-manifest.8a0be820b796b153c97ba206d9753bdb.js", "https://storage.googleapis.com/workbox-cdn/releases/3.6.2/workbox-sw.js");
workbox.precaching.precacheAndRoute(self.__precacheManifest || []);
workbox.routing.registerRoute(
/.*\.mp4/,
new workbox.strategies.CacheFirst({
cacheName: 'videos',
plugins: [
new workbox.cacheableResponse.Plugin({ statuses: [200] }),
new workbox.rangeRequests.Plugin(),
],
}),
);
If forgot to mention previously, but I've also added crossOrigin="anonymous" attribute to the video elements.
EDIT:
Repro that demonstrates it does not work as expected on Safari: https://github.com/acostalima/workbox-range-requests-mp4-demo
There's specific guidance for this use case in the "Serve cached audio and video" recipe in the Workbox documentation.
You can continue using the workbox-webpack-plugin, but I'd suggest using it in InjectManifest mode, which will give you control over the top-level service worker file. That will in turn make it possible to follow the recipe.
This documentation has guidance on configuring workbox-webpack-plugin in InjectManifest mode.
I had the same issue with Safari and managed to resolve it by removing my video from the precahe list self.__precacheManifest and instead by adding it in the service worker's install handler:
self.addEventListener('install', (event) => {
const urls = [/* videoUrl */];
const cacheName = 'videos';
event.waitUntil(caches.open(cacheName).then((cache) => cache.addAll(urls)));
});
Looking at the logs, it seemed that otherwise only the precache was used to respond to the request for the video resource and not the router.
Although the docs say that adding mp4s to the precache cache and then configuring the range plugin to handle precache mp4s is supposed to work, in practice, it wasn't. Removing mp4s from the precache and configuring your own video cache with the range plugin did the trick for me. Don't forget to add the crossorigin="anonymous" tag to your videos!
Here's how I did it (webpack 5, workbox 6):
// src/service-worker.js
import { CacheableResponsePlugin } from 'workbox-cacheable-response';
import { cacheNames } from 'workbox-core';
import { precacheAndRoute } from 'workbox-precaching';
import { RangeRequestsPlugin } from 'workbox-range-requests';
import { registerRoute } from 'workbox-routing';
import { CacheFirst } from 'workbox-strategies';
const allEntries = self.__WB_MANIFEST; // Injected by WorkboxWebpackPlugin at compile time
const videoEntries = allEntries.filter((entry) => entry.url.endsWith('.mp4'));
const restEntries = allEntries.filter((entry) => !entry.url.endsWith('.mp4'));
precacheAndRoute(restEntries);
const videoCacheName = `${cacheNames.prefix}-videos-${cacheNames.suffix}`;
self.addEventListener('install', (event) => {
const allVideosAddedToCache = caches.open(videoCacheName).then((videoCache) => {
const videoUrls = videoEntries.map((entry) => entry.url);
return videoCache.addAll(videoUrls);
});
event.waitUntil(allVideosAddedToCache);
});
registerRoute(
(route) => route.url.pathname.endsWith('.mp4'),
new CacheFirst({
cacheName: videoCacheName,
plugins: [new CacheableResponsePlugin({ statuses: [200] }), new RangeRequestsPlugin()],
})
);
// webpack.config.js
plugins: [
new WorkboxWebpackPlugin.InjectManifest({
swSrc: 'src/service-worker.js',
}),
]
// index.tsx
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js');
});
}