NativeScript / NativeScript/NativeScript
Angular Module error when updating my app and module not found using `[hash]` in filename
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 25.7k
- Forks
- 1.7k
- Avg merge
- 1d 5h
- Merged PRs (30d)
- 35
Description
Environment
- CLI: 7.2.1
- Cross-platform modules: 7.1.4
- Android Runtime: 7.0.1
- iOS Runtime: 7.2.0
- XCode Version: 12.4 & 13
- Plugin(s): lots. Will add on request. Core:
"@angular/core": "11.2.6",
"@nativescript/angular": "11.0.1",
"@nativescript/theme": "3.0.1",
"@nativescript/types": "7.3.0",
"@nativescript/webpack": "4.1.0",
"webpack": "4.46.0",
Describe the bug
Issue with a bunch of moving parts. We have lazy loaded module routes in an app.module.ts, when updating my app on testflight or the app store we had reports of users not being able to navigate in our app. I'm not too well versed on the bundle extraction process in nativescript so I'm unsure what the root cause is.
Upon inspection the error was:
[ReferenceError: Cannot access 'MyModule' before initialization]
and the code where this error threw was in a try/catch around a standard routerExtensions.navigate call.
Since this worked if the app was uninstalled/reinstalled but not when updating I started looking at what could be a problem. It appears that for my scenario (NS+Angular+Webpack default config) some old app files can be used in the new app, particularly when using lazy loaded routes which chunk out as 1.js, 2.js, 3.js and so-on.
Workaround
Initial workaround was to add file hashing to the webpack config but that lead to a "Module not found: ." error on boot.
Our workaround so far has been to add chunk hashing to the webpack config, however this involved a bit of a hack becasue the main entry in dist/package.json . It would be nice if this were easily doable or the default in these kinds of projects.
Posting the workaround here in case anyone has the same sort of pain that I did:
webpack.custom.config.js:
const defaultConfig = require('./webpack.config');
const nsWebpack = require('@nativescript/webpack');
const path = require('path');
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
const WebpackManifestReplace = require('webpack-manifest-replaces');
// ...
module.exports = (env) => {
let config = defaultConfig(env);
config = addCacheBusting(env, config);
return config;
};
function addCacheBusting(env, config) {
const platform = env && ((env.android && 'android') || (env.ios && 'ios'));
const projectRoot = __dirname;
const dist = path.resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot));
// Set output.filename to ensure hashes change
config.output.filename = '[name].[hash:8].js';
config.output.chunkFilename = '[name].[hash:8].js';
// Replace the original GenerateEntryPoints plugin to include the .js extension
config.plugins.forEach((plugin) => {
if(plugin.constructor && plugin.constructor.name === 'GenerateNativeScriptEntryPointsPlugin') {
plugin.appEntryName = 'bundle.js';
}
})
// Add a manifest.json
config.plugins.push(new WebpackManifestPlugin());
// Replace the contents of package.json's main entry with bundle.[hash].js
config.plugins.push(
new WebpackManifestReplace({
basedir: dist,
src: 'package.json',
manifestFilename: 'manifest.json',
}),
);
return config;
}
nativescript.config.ts:
import { NativeScriptConfig } from '@nativescript/core';
export default {
// ...
webpackConfigPath: 'webpack.custom.config.js',fig;
};
To Reproduce
Create an NS-angular project with lazy loaded routes. Update the child modules & update on iOS. Navigate to the route that loads the child module.
Expected behavior
The app should smoothly update to new code, without leaving old code behind.
Sample project
Unavailable in public domain, can discuss privately upon request.
Additional context
Awaiting update to NS 8.1.* because we can't go live with this issue in play: https://github.com/NativeScript/NativeScript/issues/9263
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with webpack.custom.config.js, nativescript.config.ts, and the generated package.json and manifest.json; inspect how GenerateNativeScriptEntryPointsPlugin handles bundle and chunk names. Reproduce an update with lazy-loaded routes on iOS and navigate to a child module. Done means updated apps load the new route without retaining old chunks or raising the reported module errors.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- angular, ios, typescript, webpack
- Domain
- build-system, mobile
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 28/100