I have multi module application, where some of my modules are lazily loaded, and so the output files in dist folder looks like this 1.d2ef1******8da.chunk.js, 2.dsfd3******8da.chunk.js and like wise. The problem is, if I create a new build for the production, then the hash changes and so the file names. Suppose a user has not refreshed the page, they still will try to lazily load the old file which will be shown as file not found. In such case my page hangs. How should I handle it ?
You can make use of Angular Service Workers to change your app into a PWA (Progressive Web Application).
It makes use of angular service workers to alert users to reload if a new version of app is deployed.
For Ex:
Install #angular/service-worker, add it to package.json and install dependencies.
Import ServiceWorkerModule in AppModule:
import { ServiceWorkerModule } from '#angular/service-worker';
Register it in the AppModule imports array:
ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production })
Use it in app root component:
import { Component, OnInit } from "#angular/core";
import { SwUpdate } from "#angular/service-worker";
export class AppComponent implements OnInit {
constructor(private swUpdate: SwUpdate){}
ngOnInit(): void {
if (this.swUpdate.isEnabled) {
this.swUpdate.available.subscribe(() => {
if (confirm("A New version of site is available. Load New Version?")) {
window.location.reload();
}
});
}
}
}
If you are on angular 4 and cli ~1.6. The process should be same.
npm install #angular/service-worker
add it in App Module as explained above
create a ngsw-config.json file in your app’s src directory.
{
"index": "/index.html",
"assetGroups": [{
"name": "app",
"installMode": "prefetch",
"resources": {
"files": [
"/favicon.ico",
"/index.html"
],
"versionedFiles": [
"/*.bundle.css",
"/*.bundle.js",
"/*.chunk.js"
]
}
}, {
"name": "assets",
"installMode": "lazy",
"updateMode": "prefetch",
"resources": {
"files": [
"/assets/**"
]
}
}]
}
Trying it Out
With the configuration in place, we can build the app for production (ng build --prod) and test it out using a local static server using -
npx http-server /dist
Most of the steps apart from #4 above are done automatically by latest angular cli command (https://angular.io/api/service-worker):
ng add #angular/pwa
Related
I'm trying to use dynamic package loading in my Sencha ExtJS App.
I created the package in my workspace (sencha generate package SR2000) and added SR2000 to the uses-Array in app.json:
"requires": [
"package-loader",
"font-awesome",
...
],
"uses": ["SR2000"],
In Application.js i added the loading to launch:
launch: function (profile) {
console.log('Current Config:', Base.config.Config.getConfig());
Ext.Package.load('SR2000');
Ext.Viewport.getController().onLaunch();
Ext.getBody().removeCls('launching');
this.callParent([profile]);
},
I then watch / build the app with option -uses:
sencha app watch -uses <build_profile>
When loading the app in the Browser i get error 404
The app is trying to load:
http://localhost:1841/build/development/wolfitsmart/resources/SR2000/SR2000.js
but the build output for the package is here:
http://localhost:1841/build/development/wolfitsmart/<build_profile>/resources/SR2000/SR2000.js
How can i get the package loader to look in the build_profile-Folder, or get the build to put the package in the resources-Folder?
I added the build_profile-Folder to resources in app.json, that did not help:
"resources": [
{
"path": "resources",
"output": "shared"
}
],
changed to:
"resources": [
{
"path": "resources",
"output": "shared"
},
{
"path": "${build.id}/resources"
}
],
Some useful instructions for building and using dynamic packages.
sencha app build -dev -pac yourpackagename /// build development
sencha app build -pac yourpackagename // build release
sencha app watch -pac yourpackagename
if (Ext.Package.isLoaded('packagename')) {
// package is loaded
} else {
Ext.Package.load('packagename').then(function () {
// package is loaded
});
}
I am building up a new Next Js app and its a stright forward way to make the app gets deployed in vercel by linking the gitlab Next js project..
For same project I am in the need to deploy it in firebase.
Things I have tried:
-> Made firebase init
That gives firebase.json ,
{
"hosting": {
"public": "public",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
}
But the above one gives the error like,
From this error I am able to get that it tries to fetch the index.html but I am not sure where it will be after npm run build ..
So I tried giving pages directory and index.js file like,
{
"hosting": {
"public": "pages",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
},
"rewrites": [{
"source": "/pages/**",
"destination": "/index.js"
},
{
"source": "**",
"destination": "/index.js"
}]
}
But this just prints the code available in index.js to the UI like,
import React, { Component } from "react";
import Router from "next/router";
export default class Index extends Component {
componentDidMount = () => {
Router.push("/landing",'');
};
render() {
return <div />;
}
}
The gitlab-ci.yml file as follows,
image: node:12.13.0-alpine
stages:
- deploy
cache:
paths:
- node_modules/
key: "$CI_BUILD_REPO"
deploy-prod:
stage: deploy
only:
- master
script:
- npm install
- npm run build
- npm install -g firebase-tools
- firebase -V
- firebase use anvisysytems --token "token_hidden"
- firebase deploy --only hosting -m "Pipe $CI_PIPELINE_ID Build $CI_BUILD_ID" --token "token_hidden"
Please help me to achieve the result of fetching the right index.html that will gets generated after building the Next Js application and make the app content load in UI instead of the errors(like above image) or code(like index.js code rendering in UI).
Firebase can host only static files,
To host NEXT js project as static files, you can use export option and then deploy it to Firebase.
https://nextjs.org/docs/advanced-features/static-html-export
I am using create-react-app and react-snapshot for pre-rendering. Serving the build using serve
serve -s build -l 80
But strangely for all the routes, only index.js is pre-rendered.
Below is the react-snapshot configuration in package.json
"reactSnapshot": {
"exclude": [
"/districts-data",
"/districts-data?*",
"/suggest-time",
"/covid-19-statistics"
],
"snapshotDelay": 300
}
I have excluded all the paths that include lazy loading.
I have gone through this answer but I am not catching anything in my service worker just kept it for PWA.
sw.js
self.addEventListener('fetch', function (event) {
});
self.addEventListener('install', function (event) {
});
self.addEventListener('activate', (event) => { });
After investing a couple of days and deep-diving in the serve code I realize the mistake I was doing is having -s option while running serve script.
serve -s build -l 80
Having -s option default all routes served from index.html.Having -s flag is essential if you are just serving build generated via Create react app else routes other than "/" will return a response 400.
You can simply use serve build if you have all the routes pre-rendered but if there are some routes for which you don't have pre-rendered HTML available (For my use case it was components using Lazy load) then you can create serve.json in public folder with specifying source and destination.
{
"rewrites": [
{ "source": "/districts-data", "destination": "/200.html" },
{ "source": "/districts-data?*", "destination": "/200.html" },
{ "source": "/suggest-time", "destination": "/200.html" },
{ "source": "/covid-19-statistics", "destination": "/200.html" }
]
}
You also need to change your serve command to serve -c serve.json build. -c is used to tell Specify custom path to serve.json.
In my React-Native application, import paths are like this.
import {
ScreenContainer,
SLButton,
SLTextInput,
} from '../../../../../components';
import { KeyBoardTypes } from '../../../../../enums';
import { SIGN_UP_FORM } from '../../../../constants/forms';
I have seen some applications, there the paths are more clear and elegant without '../../../'s. How can I achieve this in React-Native??
I saw in my solution that, in every folder there was a package.json file. I'm not sure if that is the proper way to do it.
You need to configure alias in webpack.config.js. You can find an example here and here
webpack.config.js:
alias: {
'#': path.join(__dirname, 'src')
}
your.js.file.js
import '#/utils/classComponentHooks';
if you don't use wepback for react-native (despite you can). You can also try .babelrc
[
'module-resolver',
{
root: ['./src'],
alias: {
'#': './src',
},
},
];
Starting around React Native version 0.55 (I'm not sure exactly when this was enabled) you can just use your project name as the path root.
import {DatePanel} from 'MyProject/components/panels';
import HomeScreen from 'MyProject/screens/HomeScreen';
No problems with flow, Xcode, etc.
It's possible. I've done it, but I don't recommend it. It doesn't work when xcode starts bundler because you have to do npm start -- --reset-cache. You have to use workarounds to learn your IDE understand this paths. It doesn't work with Flow.
You can use npm babel-plugin-module-resolver. Babel is used by metro budler.
.babelrc.
{
"presets": ["react-native"],
"plugins": [
[
"module-resolver",
{
"root": ["./src"],
"alias": {
"src": "./src",
"root": "./"
}
}
]
],
}
As I mention, I want to import a module but I don't understand the document.
I'm using Ionic for develop an app.
I install the module :
npm install wordnet
Instead of using ..
var wordnet = require('wordnet');
wordnet.lookup('define', function(err, definitions) {
definitions.forEach(function(definition) {
console.log(' words: %s', words.trim());
console.log(' %s', definition.glossary);
});
});
How to use the module in the Typescript file for using it function.. as
import { wordnet } from 'wordnet'
Do I need to import module in app.module.ts or in the page page.module.ts or something...?
It depends on your setup. If you're using AngularCLI, then it should find the TypeScript / JavaScript code automagically. Check your node-modules directory to make sure the code is there. If not add the --save-dev flag when you install:
npm install --save-dev wordnet
IF this library relies on binary assets or CSS files, then you may have to edit the angular-cli.json file to tell it where to find image or CSS files. Here is a snippet from the AngularCLI conversion I did in my Learn With books that shows how I set up assets and CSS.
"apps": [
{
"assets": [
"img",
{
"glob": "**/*",
"input": "../node_modules/#swimlane/ngx-datatable/release/assets/fonts",
"output": "./fonts"
}
],
"styles": [
"styles.css",
"../node_modules/bootstrap/dist/css/bootstrap.css",
"../node_modules/#swimlane/ngx-datatable/release/assets/icons.css",
"../node_modules/#swimlane/ngx-datatable/release/themes/material.css"
],
}
],
If you're using SystemJS to load modules then you'll have to set up wordnet in your SystemJS config. Generally something like this:
(function (global) {
System.config({
map: {
'wordnet': 'path/to/wordnet/code'
},
});
})(this);