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

Error with --env.snapshot in a build. ERROR in NativeScriptSnapshot. Snapshot generation failed! #1126

Open
FJALCode opened this issue Feb 20, 2020 · 4 comments

Comments

@FJALCode
Copy link

FJALCode commented Feb 20, 2020

Environment

  1. CLI: 5.4.0
  2. Node.js: 10.19.0
  3. npm: 6.13.4
  4. Platform: Linux.

Describe the bug
I tried to build the APK with

tns build android --release --bundle --env.uglify --env.aot --env.snapshot --key-store-path ......project.keystore --key-store-password ... --key-store-alias ..... --key-store-alias-password .... --copy-to ....project.apk

It didn't work from my PC, but it worked from another PC with linux, node V-10.16 and npm V-6.9.0.
I tried to recompile, clean the platform, update and downgrade the node version, etc, etc, but it didn't work either.
I'm able to run and build the APP with tns run/build android --bundle --env.uglify --env.aot --env.snapshot but I couldn't build with the keystore.

Error

ERROR in NativeScriptSnapshot. Snapshot generation failed!
Target architecture: x86
/bin/sh: 1: /tmp/snapshot-tools/mksnapshot-tools/v8-v7.4.288.25/linux-x64/mksnapshot-ia32: not found

***** Generating snapshot for armeabi-v7a *****
Executing webpack failed with exit code 2.

Package.json

{
  "name": "...",
  "nativescript": {
    "id": "...",
    "tns-ios": {
      "version": "5.4.2"
    },
    "tns-android": {
      "version": "5.4.0"
    }
  },
  "description": "NativeScript Application",
  "license": "SEE LICENSE IN <your-license-filename>",
  "repository": "<fill-your-repository-here>",
  "scripts": {
    "lint": "tslint \"src/**/*.ts\""
  },
  "dependencies": {
    "@angular/animations": "~8.0.0",
    "@angular/common": "~8.0.0",
    "@angular/compiler": "~8.0.0",
    "@angular/core": "~8.0.0",
    "@angular/forms": "~8.0.0",
    "@angular/http": "~8.0.0-beta.10",
    "@angular/platform-browser": "~8.0.0",
    "@angular/platform-browser-dynamic": "~8.0.0",
    "@angular/router": "~8.0.0",
    "@ngx-translate/core": "^11.0.1",
    "@ngx-translate/http-loader": "^4.0.0",
    "@nstudio/nativescript-cardview": "^1.0.0",
    "@nstudio/nativescript-floatingactionbutton": "^1.0.1",
    "@types/crypto-js": "^3.1.43",
    "@types/d3-ease": "^1.0.8",
    "@types/node": "^12.7.3",
    "buffer": "^5.4.2",
    "crypto-js": "^3.1.9-1",
    "d3-ease": "^1.0.5",
    "md5": "^2.2.1",
    "moment": "^2.24.0",
    "nativescript-angular": "~8.0.0",
    "nativescript-appversion": "^1.4.2",
    "nativescript-background-http": "^3.4.1",
    "nativescript-camera": "^4.5.0",
    "nativescript-geolocation": "^5.1.0",
    "nativescript-imagepicker": "^7.0.0",
    "nativescript-intl": "^3.0.0",
    "nativescript-loading-indicator": "^2.5.2",
    "nativescript-mapbox": "^4.3.1",
    "nativescript-mqtt": "^1.2.0",
    "nativescript-oauth2": "^2.1.0",
    "nativescript-permissions": "^1.3.6",
    "nativescript-plugin-firebase": "^9.0.0",
    "nativescript-social-share": "^1.5.2",
    "nativescript-sqlite": "^2.3.3",
    "nativescript-theme-core": "~1.0.4",
    "nativescript-toast": "^2.0.0",
    "nativescript-ui-chart": "^4.0.2",
    "nativescript-ui-dataform": "^3.6.0",
    "nativescript-ui-listview": "^6.4.2",
    "nativescript-ui-sidedrawer": "~6.0.0",
    "nativescript-unit-test-runner": "^0.6.4",
    "reflect-metadata": "~0.1.12",
    "rxjs": "^6.5.2",
    "rxjs-compat": "^6.5.2",
    "tns-core-modules": "~5.4.0",
    "zone.js": "~0.9.1"
  },
  "devDependencies": {
    "@angular/compiler-cli": "~8.0.0",
    "@ngtools/webpack": "~8.0.0",
    "@types/karma-chai": "0.1.1",
    "@types/mocha": "5.2.7",
    "chai": "4.2.0",
    "codelyzer": "~4.5.0",
    "karma": "4.2.0",
    "karma-chai": "0.1.0",
    "karma-mocha": "1.3.0",
    "karma-nativescript-launcher": "0.4.0",
    "karma-webpack": "4.0.2",
    "mocha": "6.1.4",
    "nativescript-dev-sass": "^1.7.0",
    "nativescript-dev-typescript": "~0.10.0",
    "nativescript-dev-webpack": "^0.24.1",
    "tslint": "~5.11.0"
  },
..
}

webpack.config.js

const { join, relative, resolve, sep, dirname } = require("path");

const webpack = require("webpack");
const nsWebpack = require("nativescript-dev-webpack");
const nativescriptTarget = require("nativescript-dev-webpack/nativescript-target");
const { nsReplaceBootstrap } = require("nativescript-dev-webpack/transformers/ns-replace-bootstrap");
const { nsReplaceLazyLoader } = require("nativescript-dev-webpack/transformers/ns-replace-lazy-loader");
const { nsSupportHmrNg } = require("nativescript-dev-webpack/transformers/ns-support-hmr-ng");
const { getMainModulePath } = require("nativescript-dev-webpack/utils/ast-utils");
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 TerserPlugin = require("terser-webpack-plugin");
const { getAngularCompilerPlugin } = require("nativescript-dev-webpack/plugins/NativeScriptAngularCompilerPlugin");
const hashSalt = Date.now().toString();

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 AngularCompilerPlugin = getAngularCompilerPlugin(platform);
    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_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
        sourceMap, // --env.sourceMap
        hiddenSourceMap, // --env.hiddenSourceMap
        hmr, // --env.hmr,
        unitTesting, // --env.unitTesting
    } = env;

    const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap;
    const externals = nsWebpack.getConvertedExternals(env.externals);
    const appFullPath = resolve(projectRoot, appPath);
    const appResourcesFullPath = resolve(projectRoot, appResourcesPath);
    const tsConfigName = "tsconfig.tns.json";
    const entryModule = `${nsWebpack.getEntryModule(appFullPath, platform)}.ts`;
    const entryPath = `.${sep}${entryModule}`;
    const entries = { bundle: entryPath };
    if (platform === "ios") {
        entries["tns_modules/tns-core-modules/inspector_modules"] = "inspector_modules.js";
    };

    const ngCompilerTransformers = [];
    const additionalLazyModuleResources = [];
    if (aot) {
        ngCompilerTransformers.push(nsReplaceBootstrap);
    }

    if (hmr) {
        ngCompilerTransformers.push(nsSupportHmrNg);
    }

    // when "@angular/core" is external, it's not included in the bundles. In this way, it will be used
    // directly from node_modules and the Angular modules loader won't be able to resolve the lazy routes
    // fixes https://github.com/NativeScript/nativescript-cli/issues/4024
    if (env.externals && env.externals.indexOf("@angular/core") > -1) {
        const appModuleRelativePath = getMainModulePath(resolve(appFullPath, entryModule), tsConfigName);
        if (appModuleRelativePath) {
            const appModuleFolderPath = dirname(resolve(appFullPath, appModuleRelativePath));
            // include the lazy loader inside app module
            ngCompilerTransformers.push(nsReplaceLazyLoader);
            // include the new lazy loader path in the allowed ones
            additionalLazyModuleResources.push(appModuleFolderPath);
        }
    }

    const ngCompilerPlugin = new AngularCompilerPlugin({
        hostReplacementPaths: nsWebpack.getResolver([platform, "tns"]),
        platformTransformers: ngCompilerTransformers.map(t => t(() => ngCompilerPlugin, resolve(appFullPath, entryModule), projectRoot)),
        mainPath: join(appFullPath, entryModule),
        tsConfigPath: join(__dirname, tsConfigName),
        skipCodeGeneration: !aot,
        sourceMap: !!isAnySourceMapEnabled,
        additionalLazyModuleResources: additionalLazyModuleResources
    });

    let sourceMapFilename = nsWebpack.getSourceMapFilename(hiddenSourceMap, __dirname, dist);

    const config = {
        mode: uglify ? "production" : "development",
        context: appFullPath,
        externals,
        watchOptions: {
            ignored: [
                appResourcesFullPath,
                // Don't watch hidden files
                "**/.*",
            ]
        },
        target: nativescriptTarget,
        entry: entries,
        output: {
            pathinfo: false,
            path: dist,
            sourceMapFilename,
            libraryTarget: "commonjs2",
            filename: "[name].js",
            globalObject: "global",
            hashSalt
        },
        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: hiddenSourceMap ? "hidden-source-map" : (sourceMap ? "inline-source-map" : "none"),
        optimization: {
            runtimeChunk: "single",
            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 TerserPlugin({
                    parallel: true,
                    cache: true,
                    sourceMap: isAnySourceMapEnabled,
                    terserOptions: {
                        output: {
                            comments: false,
                            semicolons: !isAnySourceMapEnabled
                        },
                        compress: {
                            // The Android SBG has problems parsing the output
                            // when these options are enabled
                            'collapse_vars': platform !== "android",
                            sequences: platform !== "android",
                        }
                    }
                })
            ],
        },        
        module: {
            rules: [
                {
                    test: nsWebpack.getEntryPathRegExp(appFullPath, 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
                                unitTesting,
                                appFullPath,
                                projectRoot,
                            }
                        },
                    ].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: [
                        "nativescript-dev-webpack/style-hot-loader",
                        { loader: "css-loader", options: { url: false } }
                    ]
                },
                {
                    test: /[\/|\\]app\.scss$/,
                    use: [
                        "nativescript-dev-webpack/style-hot-loader",
                        { loader: "css-loader", options: { 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"] },

                {
                    test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/,
                    use: [
                        "nativescript-dev-webpack/moduleid-compat-loader",
                        "nativescript-dev-webpack/lazy-ngmodule-hot-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",
                "process": undefined,
            }),
            // Remove all files from the out dir.
            new CleanWebpackPlugin([`${dist}/**/*`]),
            // Copy assets to out dir. Add your own globs as needed.
            new CopyWebpackPlugin([
                { from: { glob: "fonts/**" } },
                { from: { glob: "**/*.json" } },
                { from: { glob: "**/*.jpg" } },
                { from: { glob: "**/*.png" } },
            ], { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }),
            // Generate a bundle starter script and activate it in package.json
            new nsWebpack.GenerateBundleStarterPlugin(
                // Don't include `runtime.js` when creating a snapshot. The plugin
                // configures the WebPack runtime to be generated inside the snapshot
                // module and no `runtime.js` module exist.
                (snapshot ? [] : ["./runtime"])
                    .concat([
                        "./vendor",
                        "./bundle",
                    ])
            ),
            // For instructions on how to set up workers with webpack
            // check out https://github.com/nativescript/worker-loader
            new NativeScriptWorkerPlugin(),
            ngCompilerPlugin,
            // Does IPC communication with the {N} CLI to notify events when running in watch mode.
            new nsWebpack.WatchStateLoggerPlugin(),
        ],
    };

    // Copy the native app resources to the out dir
    // only if doing a full build (tns run/build) and not previewing (tns preview)
    if (!externals || externals.length === 0) {
        config.plugins.push(new CopyWebpackPlugin([
            {
                from: `${appResourcesFullPath}/${appResourcesPlatformDir}`,
                to: `${dist}/App_Resources/${appResourcesPlatformDir}`,
                context: projectRoot
            },
        ]));
    }


    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,
        }));
    }

    if (hmr) {
        config.plugins.push(new webpack.HotModuleReplacementPlugin());
    }

    return config;
};
@NickIliev
Copy link
Contributor

@FJALCode the snapshot flag will be respected only in a release which explains why you are successfully doing a debug build (where the snapshot flag is simply ignored).

The likely reason for your issue is a mismatch of versions. I've noticed you are using CLI version 5.4.0 while using one of the latest versions of nativescript-dev-webpack. My suggestion is to migrate to the latest versions of all NativeScript related packages (CLI, modules. webpack)

@FJALCode
Copy link
Author

FJALCode commented Mar 19, 2020

@NickIliev I couldn't migrate the Nativescript version because I need the Mapbox Plugin, and that plugin for now, only works with Nativescript <5.4.
I was following this tutorial for create the build version, and this tutorial for debug version.

I don't know why It didn't work from my PC, but it worked from another PC with same linux, Node and Nativescript version. I have formatted my pc, but it still fails, you may know the reason ¿?¿?

@saschaarthur
Copy link

saschaarthur commented Apr 22, 2020

This one here is related to: NativeScript/nativescript-cli#5298

As far as i see it now its your build env.

Youre missing stuff on your os, you can use my docker container: https://hub.docker.com/r/scratchy/nativescript-cli
in this i fixed this issue by adding "libx32gcc-8-dev" and "xxd"

@saschaarthur
Copy link

saschaarthur commented Apr 22, 2020

The likely reason for your issue is a mismatch of versions. I've noticed you are using CLI version 5.4.0 while using one of the latest versions of nativescript-dev-webpack. My suggestion is to migrate to the latest versions of all NativeScript related packages (CLI, modules. webpack)

This is just not correct, just letting someone random upgrade stuff is not a good solution and brings far more issues with it. In general the build should work for every version, and they should be reproducable (https://en.wikipedia.org/wiki/Reproducible_builds) at any time (even if i trigger a build for an old version years ago it should work, because the build environment should be clean and frozen).

Also hes just missing dependencies (the one i posted above), it has nothing today with his versions (or at least it should otherwise this complete build setup is not correct). Especially as far as i see it atm the build process is somehow running parts in an docker environment (which is a good first step for reproducable builds..)

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

No branches or pull requests

3 participants