Skip to content
This repository has been archived by the owner on Aug 7, 2021. It is now read-only.

no such file or directory, stat app-routing.module.ngfactory.js #566

Closed
9 tasks done
fthuin opened this issue Jun 14, 2018 · 1 comment · Fixed by #574
Closed
9 tasks done

no such file or directory, stat app-routing.module.ngfactory.js #566

fthuin opened this issue Jun 14, 2018 · 1 comment · Fixed by #574
Assignees
Labels

Comments

@fthuin
Copy link

fthuin commented Jun 14, 2018

Issue Checklist

Tell us about the problem

Hi, first this issue might look like a duplicate of #547, but it is not because the issue was marked resolved in 0.13 and I use that version.

Step to reproduce:

  1. Go to your NS+Angular project
  2. tns run android --bundle --env.aot
  3. Modify a file
  4. Wait for file watch, then read this in the console
Error: ENOENT: no such file or directory, stat '/Users/fthuin/Documents/tabacstop-nativescript/app/app-routing.module.ngfactory.js'
    at Object.fs.statSync (fs.js:948:11)
    at Object.statSync (/Users/fthuin/Documents/tabacstop-nativescript/node_modules/graceful-fs/polyfills.js:297:22)
    at Storage.provideSync (/Users/fthuin/Documents/tabacstop-nativescript/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:98:13)
    at CachedInputFileSystem.statSync (/Users/fthuin/Documents/tabacstop-nativescript/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:251:28)
    at VirtualFileSystemDecorator.statSync (/Users/fthuin/Documents/tabacstop-nativescript/node_modules/@ngtools/webpack/src/packages/ngtools/webpack/src/virtual_file_system_decorator.ts:74:44)
    at virtualFilesStats._virtualInputFileSystem.getVirtualFilesPaths.map (/Users/fthuin/Documents/tabacstop-nativescript/node_modules/@ngtools/webpack/src/packages/ngtools/webpack/src/virtual_file_system_decorator.ts:133:48)
    at Array.map (<anonymous>)
    at newCallback (/Users/fthuin/Documents/tabacstop-nativescript/node_modules/@ngtools/webpack/src/packages/ngtools/webpack/src/virtual_file_system_decorator.ts:131:10)
    at Watchpack.watcher.once (/Users/fthuin/Documents/tabacstop-nativescript/node_modules/webpack/lib/node/NodeWatchFileSystem.js:43:4)
    at Object.onceWrapper (events.js:317:30)
    at emitTwo (events.js:126:13)
    at Watchpack.emit (events.js:214:7)
    at Watchpack._onTimeout (/Users/fthuin/Documents/tabacstop-nativescript/node_modules/watchpack/lib/watchpack.js:144:7)
    at ontimeout (timers.js:475:11)
    at tryOnTimeout (timers.js:310:5)
    at Timer.listOnTimeout (timers.js:270:5)
  1. Look for the app-routing.module.ngfactory.{js|ts}, it doesn't exist. Doesn't seem created/needed by NS Angular in most template examples.

Local environment

  • Mac
  • node v8.9.4
  • NativeScript CLI version 4.1.0

Project data

  • Platform you are building the app for both Android and iOS
  • Node dependencies:
  "dependencies": {
    "@angular/animations": "~6.0.0",
    "@angular/common": "~6.0.0",
    "@angular/compiler": "~6.0.0",
    "@angular/core": "~6.0.0",
    "@angular/forms": "~6.0.0",
    "@angular/http": "~6.0.0",
    "@angular/platform-browser": "~6.0.0",
    "@angular/platform-browser-dynamic": "~6.0.0",
    "@angular/router": "~6.0.0",
    "@ngx-translate/core": "^9.1.1",
    "@ngx-translate/http-loader": "^2.0.1",
    "@types/lodash": "^4.14.107",
    "@types/q": "^1.5.0",
    "lodash": "^4.17.5",
    "moment": "^2.22.1",
    "nativescript-angular": "~6.0.0",
    "nativescript-background-http": "^3.2.3",
    "nativescript-checkbox": "^3.0.3",
    "nativescript-email": "^1.5.2",
    "nativescript-facebook": "2.2.0",
    "nativescript-feedback": "^1.1.2",
    "nativescript-fresco": "^3.0.7",
    "nativescript-image-black-and-white": "^1.0.3",
    "nativescript-imagepicker": "^6.0.1",
    "nativescript-iqkeyboardmanager": "^1.3.0",
    "nativescript-permissions": "^1.2.3",
    "nativescript-phone": "^1.3.1",
    "nativescript-theme-core": "~1.0.4",
    "nativescript-toast": "^1.4.6",
    "nativescript-ui-listview": "^3.5.7",
    "nativescript-websockets": "^1.4.0",
    "q": "^1.5.1",
    "reflect-metadata": "~0.1.10",
    "rxjs": "~6.0.0 || >=6.1.0",
    "rxjs-compat": "^6.2.1",
    "tns-core-modules": "~4.1.0",
    "zone.js": "^0.8.26"
  },
  "devDependencies": {
    "@angular-devkit/core": "~0.7.0-beta.1",
    "@angular/compiler-cli": "~6.0.0",
    "@ngtools/webpack": "~6.1.0-beta.1",
    "babel-traverse": "6.26.0",
    "babel-types": "6.26.0",
    "babylon": "6.18.0",
    "clean-webpack-plugin": "~0.1.19",
    "codelyzer": "~4.0.2",
    "copy-webpack-plugin": "~4.5.1",
    "css-loader": "~0.28.11",
    "extract-text-webpack-plugin": "~3.0.2",
    "lazy": "1.0.11",
    "nativescript-dev-sass": "^1.6.0",
    "nativescript-dev-typescript": "^0.7.1",
    "nativescript-dev-webpack": "^0.13.0",
    "nativescript-worker-loader": "~0.9.0",
    "ngx-translate-extract-csv": "^1.1.1",
    "prettier": "^1.12.1",
    "raw-loader": "~0.5.1",
    "resolve-url-loader": "~2.3.0",
    "sass-loader": "~7.0.1",
    "tns-platform-declarations": "^4.1.0",
    "tslint": "~5.8.0",
    "tslint-config-prettier": "^1.12.0",
    "typescript": "~2.7.2",
    "uglifyjs-webpack-plugin": "~1.2.5",
    "webpack": "~4.6.0",
    "webpack-bundle-analyzer": "~2.13.0",
    "webpack-cli": "~2.1.3",
    "webpack-sources": "~1.1.0"
  },
  • Webpack configuration:
const { join, relative, resolve, sep } = require("path");

const webpack = require("webpack");
const nsWebpack = require("nativescript-dev-webpack");
const nativescriptTarget = require("nativescript-dev-webpack/nativescript-target");
const { PlatformReplacementHost } = require("nativescript-dev-webpack/host/platform");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
const { NativeScriptWorkerPlugin } = require("nativescript-worker-loader/NativeScriptWorkerPlugin");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const { AngularCompilerPlugin } = require("@ngtools/webpack");

module.exports = env => {
    // Add your custom Activities, Services and other Android app components here.
    const appComponents = [
        "tns-core-modules/ui/frame",
        "tns-core-modules/ui/frame/activity",
    ];

    const platform = env && (env.android && "android" || env.ios && "ios");
    if (!platform) {
        throw new Error("You need to provide a target platform!");
    }

    const extensions = ["tns", platform];
    const platformHost = new PlatformReplacementHost(extensions);

    const projectRoot = __dirname;

    // Default destination inside platforms/<platform>/...
    const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot));
    const appResourcesPlatformDir = platform === "android" ? "Android" : "iOS";

    const {
        // The 'appPath' and 'appResourcesPath' values are fetched from
        // the nsconfig.json configuration file
        // when bundling with `tns run android|ios --bundle`.
        appPath = "app",
        appResourcesPath = "app/App_Resources",

        // You can provide the following flags when running 'tns run android|ios'
        aot, // --env.aot
        snapshot, // --env.snapshot
        uglify, // --env.uglify
        report, // --env.report
    } = env;

    const appFullPath = resolve(projectRoot, appPath);
    const appResourcesFullPath = resolve(projectRoot, appResourcesPath);

    const entryModule = aot ?
        nsWebpack.getAotEntryModule(appFullPath) : 
        `${nsWebpack.getEntryModule(appFullPath)}.ts`;
    const entryPath = `.${sep}${entryModule}`;

    const config = {
        mode: uglify ? "production" : "development",
        context: appFullPath,
        watchOptions: {
            ignored: [
                appResourcesFullPath,
                // Don't watch hidden files
                "**/.*",
            ]
        },
        target: nativescriptTarget,
        entry: {
            bundle: entryPath,
        },
        output: {
            pathinfo: false,
            path: dist,
            libraryTarget: "commonjs2",
            filename: "[name].js",
            globalObject: "global",
        },
        resolve: {
            extensions: [".ts", ".js", ".scss", ".css"],
            // Resolve {N} system modules from tns-core-modules
            modules: [
                resolve(__dirname, "node_modules/tns-core-modules"),
                resolve(__dirname, "node_modules"),
                "node_modules/tns-core-modules",
                "node_modules",
            ],
            alias: {
                '~': appFullPath
            },
            symlinks: true
        },
        resolveLoader: {
            symlinks: false
        },
        node: {
            // Disable node shims that conflict with NativeScript
            "http": false,
            "timers": false,
            "setImmediate": false,
            "fs": "empty",
            "__dirname": false,
        },
        devtool: "none",
        optimization: {
            splitChunks: {
                cacheGroups: {
                    vendor: {
                        name: "vendor",
                        chunks: "all",
                        test: (module, chunks) => {
                            const moduleName = module.nameForCondition ? module.nameForCondition() : '';
                            return /[\\/]node_modules[\\/]/.test(moduleName) ||
                                    appComponents.some(comp => comp === moduleName);
                        },
                        enforce: true,
                    },
                }
            },
            minimize: !!uglify,
            minimizer: [
                new UglifyJsPlugin({
                    uglifyOptions: {
                        parallel: true,
                        cache: true,
                        output: {
                            comments: false,
                        },
                        compress: {
                            // The Android SBG has problems parsing the output
                            // when these options are enabled
                            'collapse_vars': platform !== "android",
                            sequences: platform !== "android",
                        }
                    }
                })
            ],
        },
        module: {
            rules: [
                {
                    test: new RegExp(entryPath),
                    use: [
                        // Require all Android app components
                        platform === "android" && {
                            loader: "nativescript-dev-webpack/android-app-components-loader",
                            options: { modules: appComponents }
                        },

                        {
                            loader: "nativescript-dev-webpack/bundle-config-loader",
                            options: {
                                angular: true,
                                loadCss: !snapshot, // load the application css if in debug mode
                            }
                        },
                    ].filter(loader => !!loader)
                },

                { test: /\.html$|\.xml$/, use: "raw-loader" },

                // tns-core-modules reads the app.css and its imports using css-loader
                {
                    test: /[\/|\\]app\.css$/,
                    use: {
                        loader: "css-loader",
                        options: { minimize: false, url: false },
                    }
                },
                {
                    test: /[\/|\\]app\.scss$/,
                    use: [
                        { loader: "css-loader", options: { minimize: false, url: false } },
                        "sass-loader"
                    ]
                },

                // Angular components reference css files and their imports using raw-loader
                { test: /\.css$/, exclude: /[\/|\\]app\.css$/, use: "raw-loader" },
                { test: /\.scss$/, exclude: /[\/|\\]app\.scss$/, use: ["raw-loader", "resolve-url-loader", "sass-loader"] },

                // Compile TypeScript files with ahead-of-time compiler.
                {
                    test: /.ts$/, use: [
                        "nativescript-dev-webpack/moduleid-compat-loader",
                        "@ngtools/webpack",
                    ]
                },

                // Mark files inside `@angular/core` as using SystemJS style dynamic imports.
                // Removing this will cause deprecation warnings to appear.
                {
                    test: /[\/\\]@angular[\/\\]core[\/\\].+\.js$/,
                    parser: { system: true },
                },
            ],
        },
        plugins: [
            // Define useful constants like TNS_WEBPACK
            new webpack.DefinePlugin({
                "global.TNS_WEBPACK": "true",
            }),
            // Remove all files from the out dir.
            new CleanWebpackPlugin([ `${dist}/**/*` ]),
            // Copy native app resources to out dir.
            new CopyWebpackPlugin([
                {
                    from: `${appResourcesFullPath}/${appResourcesPlatformDir}`,
                    to: `${dist}/App_Resources/${appResourcesPlatformDir}`,
                    context: projectRoot
                },
            ]),
            // Copy assets to out dir. Add your own globs as needed.
            new CopyWebpackPlugin([
                { from: "fonts/**" },
                { from: "**/*.jpg" },
                { from: "**/*.png" },
                { from: "i18n/*.json" },
            ], { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }),
            // Generate a bundle starter script and activate it in package.json
            new nsWebpack.GenerateBundleStarterPlugin([
                "./vendor",
                "./bundle",
            ]),
            // For instructions on how to set up workers with webpack
            // check out https://github.com/nativescript/worker-loader
            new NativeScriptWorkerPlugin(),

            new AngularCompilerPlugin({
                host: platformHost,
                entryModule: resolve(appPath, "app.module#AppModule"),
                tsConfigPath: join(__dirname, "tsconfig.esm.json"),
                skipCodeGeneration: !aot,
            }),
            // Does IPC communication with the {N} CLI to notify events when running in watch mode.
            new nsWebpack.WatchStateLoggerPlugin(),
        ],
    };

    if (report) {
        // Generate report files for bundles content
        config.plugins.push(new BundleAnalyzerPlugin({
            analyzerMode: "static",
            openAnalyzer: false,
            generateStatsFile: true,
            reportFilename: resolve(projectRoot, "report", `report.html`),
            statsFilename: resolve(projectRoot, "report", `stats.json`),
        }));
    }

    if (snapshot) {
        config.plugins.push(new nsWebpack.NativeScriptSnapshotPlugin({
            chunk: "vendor",
            angular: true,
            requireModules: [
                "reflect-metadata",
                "@angular/platform-browser",
                "@angular/core",
                "@angular/common",
                "@angular/router",
                "nativescript-angular/platform-static",
                "nativescript-angular/router",
            ],
            projectRoot,
            webpackConfig: config,
        }));
    }

    return config;
};

@sis0k0

@fthuin fthuin changed the title ENOENT: no such file or directory, stat app-routing.module.ngfactory.js no such file or directory, stat app-routing.module.ngfactory.js Jun 14, 2018
@sis0k0 sis0k0 self-assigned this Jun 19, 2018
@sis0k0 sis0k0 added the bug label Jun 19, 2018
@sis0k0
Copy link
Contributor

sis0k0 commented Jun 19, 2018

Thanks for reporting that!

sis0k0 added a commit that referenced this issue Jun 19, 2018
Calling `require.context` for the app directory adds a `ContextDependency` in webpack for it. That causes every change inside the app/ directory to emit a change event for the whole directory.
There's a logic in the TypeScript compiler host (from
[@ngtools/webpack](https://github.com/angular/angular-cli/blob/master/packages/ngtools/webpack/src/compiler_host.ts#L235))
that invalidates all files in the changed directory. The invalidation
removes all cached information for the virtual files produced by the
Angular AoT compilation (ngfactory files, etc.). Since these files are
not in the cache anymore, webpack tries to resolve them from the
filesystem and fails. The solution is to remove the `ContextDependency`
for the `app` dir, which should also make the rebuilds much faster.

fixes #566
sis0k0 added a commit that referenced this issue Jun 22, 2018
Calling `require.context` for the app directory adds a `ContextDependency` in webpack for it. That causes every change inside the app/ directory to emit a change event for the whole directory.
There's a logic in the TypeScript compiler host (from
[@ngtools/webpack](https://github.com/angular/angular-cli/blob/master/packages/ngtools/webpack/src/compiler_host.ts#L235))
that invalidates all files in the changed directory. The invalidation
removes all cached information for the virtual files produced by the
Angular AoT compilation (ngfactory files, etc.). Since these files are
not in the cache anymore, webpack tries to resolve them from the
filesystem and fails. The solution is to remove the `ContextDependency`
for the `app` dir, which should also make the rebuilds much faster.

fixes #566
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants