NativeScript / nativescript-dev-webpack

A package to help with webpacking NativeScript apps.
Apache License 2.0
97 stars 49 forks source link

Error: Cannot find module '@nativescript/webpack/nativescript-target' #1156

Open pieveee opened 3 years ago

pieveee commented 3 years ago

Environment Provide version numbers for the following components (information can be retrieved by running tns info in your project folder or by inspecting the package.json of the project):

package.json:

{
  "name": "aurora-spa",
  "version": "0.0.0",
  "scripts": {
    "android": "ns run android --no-hmr",
    "ios": "ns run ios --no-hmr",
    "mobile": "ns run",
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@nativescript/angular": "~11.8.0",
    "@nativescript/core": "~8.0.0",
    "@nativescript/theme": "~2.5.0",
    "reflect-metadata": "~0.1.12",
    "tslib": "^1.10.0",
    "@angular/animations": "~12.0.5",
    "@angular/common": "~12.0.5",
    "@angular/compiler": "~12.0.5",
    "@angular/core": "~12.0.5",
    "@angular/forms": "~12.0.5",
    "@angular/platform-browser": "~12.0.5",
    "@angular/platform-browser-dynamic": "~12.0.5",
    "@angular/router": "~12.0.5",
    "@auth0/angular-jwt": "5.0.2",
    "@fortawesome/angular-fontawesome": "^0.9.0",
    "@fortawesome/fontawesome-svg-core": "^1.2.28",
    "@fortawesome/free-regular-svg-icons": "^5.15.1",
    "@fortawesome/free-solid-svg-icons": "^5.15.1",
    "@ngrx/effects": "^12.1.0",
    "@ngrx/store": "^12.1.0",
    "axios": "^0.19.1",
    "bootstrap": "^4.4.1",
    "core-js": "^2.5.4",
    "ng-sapphiredb": "^3.1.8",
    "ngx-bootstrap": "^5.6.1",
    "rxjs": "~6.6.7",
    "sapphiredb": "^3.0.0",
    "zone.js": "~0.11.4"
  },
  "devDependencies": {
    "@angular/cli": "~12.0.5",
    "@angular/compiler-cli": "~12.0.5",
    "@angular/language-service": "~12.0.5",
    "@nativescript/android": "8.0.0",
    "@nativescript/schematics": "^11.2.0",
    "@nativescript/tslint-rules": "~0.0.5",
    "@ngrx/store-devtools": "^12.1.0",
    "@types/jasmine": "~2.8.8",
    "@types/jasminewd2": "~2.0.3",
    "@types/node": "^12.11.1",
    "codelyzer": "^5.1.2",
    "jasmine-core": "~3.5.0",
    "jasmine-spec-reporter": "~5.0.0",
    "karma": "~6.3.4",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage-istanbul-reporter": "~3.0.2",
    "karma-jasmine": "~4.0.0",
    "karma-jasmine-html-reporter": "^1.5.0",
    "protractor": "~7.0.0",
    "ts-node": "~7.0.0",
    "tslint": "~6.1.0",
    "typescript": "~4.2.4",
    "@nativescript/webpack": "~5.0.0-beta.0",
    "@ngtools/webpack": "~10.0.0"
  },
  "main": "./src/main.tns.ts"
}

webpack.config.js:

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

const webpack = require('webpack');
const nsWebpack = require('@nativescript/webpack');
const nativescriptTarget = require('@nativescript/webpack/nativescript-target');
const { nsSupportHmrNg } = require('@nativescript/webpack/transformers/ns-support-hmr-ng');
const { nsTransformNativeClassesNg } = require('@nativescript/webpack/transformers/ns-transform-native-classes-ng');
const { parseWorkspaceConfig, hasConfigurations } = require('@nativescript/webpack/helpers/angular-config-parser');
const { getMainModulePath } = require('@nativescript/webpack/utils/ast-utils');
const { getNoEmitOnErrorFromTSConfig, getCompilerOptionsFromTSConfig } = require('@nativescript/webpack/utils/tsconfig-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/webpack/plugins/NativeScriptAngularCompilerPlugin');
const hashSalt = Date.now().toString();

module.exports = (env) => {
    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 {
        // The 'appPath' and 'appResourcesPath' values are fetched from
        // the nsconfig.json configuration file
        // when bundling with `tns run android|ios --bundle`.
        appPath = 'src',
        appResourcesPath = 'App_Resources',

        // You can provide the following flags when running 'tns run android|ios'
        snapshot, // --env.snapshot,
        production, // --env.production
        configuration, // --env.configuration (consistent with angular cli usage)
        projectName, // --env.projectName (drive configuration through angular projects)
        uglify, // --env.uglify
        report, // --env.report
        sourceMap, // --env.sourceMap
        hiddenSourceMap, // --env.hiddenSourceMap
        hmr, // --env.hmr,
        unitTesting, // --env.unitTesting
        testing, // --env.testing
        verbose, // --env.verbose
        ci, // --env.ci
        snapshotInDocker, // --env.snapshotInDocker
        skipSnapshotTools, // --env.skipSnapshotTools
        compileSnapshot, // --env.compileSnapshot
        appComponents = [],
        entries = {},
    } = env;

    const { fileReplacements, copyReplacements } = parseWorkspaceConfig(platform, configuration, projectName);

    const useLibs = compileSnapshot;
    const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap;
    const externals = nsWebpack.getConvertedExternals(env.externals);
    const appFullPath = resolve(projectRoot, appPath);
    const appResourcesFullPath = resolve(projectRoot, appResourcesPath);
    let tsConfigName = 'tsconfig.json';
    let tsConfigPath = resolve(projectRoot, tsConfigName);
    const tsConfigTnsName = 'tsconfig.tns.json';
    const tsConfigTnsPath = resolve(projectRoot, tsConfigTnsName);
    if (fs.existsSync(tsConfigTnsPath)) {
        // support shared angular app configurations
        tsConfigName = tsConfigTnsName;
        tsConfigPath = tsConfigTnsPath;
    }
    const tsConfigEnvName = 'tsconfig.env.json';
    const tsConfigEnvPath = resolve(projectRoot, tsConfigEnvName);
    if (hasConfigurations(configuration) && fs.existsSync(tsConfigEnvPath)) {
        // when configurations are used, switch to environments supported config
        tsConfigName = tsConfigEnvName;
        tsConfigPath = tsConfigEnvPath;
    }
    const entryModule = `${nsWebpack.getEntryModule(appFullPath, platform)}.ts`;
    const entryPath = `.${sep}${entryModule}`;
    Object.assign(entries, { bundle: entryPath }, entries);
    const areCoreModulesExternal = Array.isArray(env.externals) && env.externals.some((e) => e.indexOf('@nativescript') > -1);
    if (platform === 'ios' && !areCoreModulesExternal && !testing) {
        entries['tns_modules/inspector_modules'] = '@nativescript/core/inspector_modules';
    }

    const compilerOptions = getCompilerOptionsFromTSConfig(tsConfigPath);
    nsWebpack.processTsPathsForScopedModules({ compilerOptions });
    nsWebpack.processTsPathsForScopedAngular({ compilerOptions });

    const ngCompilerTransformers = [nsTransformNativeClassesNg];
    const additionalLazyModuleResources = [];

    const copyIgnore = { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] };
    const copyTargets = [{ from: { glob: 'assets/**', dot: false } }, { from: { glob: 'fonts/**', dot: false } }, ...copyReplacements];

    if (!production) {
        // for development purposes only
        // for example, include mock json folder
        // copyTargets.push({ from: 'tools/mockdata', to: 'assets/mockdata' });

        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 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,
        skipCodeGeneration: false,
        sourceMap: !!isAnySourceMapEnabled,
        additionalLazyModuleResources: additionalLazyModuleResources,
        compilerOptions: { paths: compilerOptions.paths },
    });

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

    const itemsToClean = [`${dist}/**/*`];
    if (platform === 'android') {
        itemsToClean.push(`${join(projectRoot, 'platforms', 'android', 'app', 'src', 'main', 'assets', 'snapshots')}`);
        itemsToClean.push(`${join(projectRoot, 'platforms', 'android', 'app', 'build', 'configurations', 'nativescript-android-snapshot')}`);
    }

    const noEmitOnErrorFromTSConfig = getNoEmitOnErrorFromTSConfig(tsConfigName);

    // Add your custom Activities, Services and other android app components here.
    appComponents.push('@nativescript/core/ui/frame', '@nativescript/core/ui/frame/activity');

    nsWebpack.processAppComponents(appComponents, platform);
    const config = {
        mode: production ? '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 @nativescript/core
            modules: [resolve(__dirname, 'node_modules/@nativescript/core'), resolve(__dirname, 'node_modules'), 'node_modules/@nativescript/core', 'node_modules'],
            alias: {
                '~/package.json': resolve(projectRoot, 'package.json'),
                '~': appFullPath,
                'tns-core-modules': '@nativescript/core',
                'nativescript-angular': '@nativescript/angular',
                ...fileReplacements,
            },
            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',
            noEmitOnErrors: noEmitOnErrorFromTSConfig,
            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: !ci,
                    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',
                            // For v8 Compatibility
                            keep_infinity: true, // for V8
                            reduce_funcs: false, // for V8
                            // custom
                            drop_console: production,
                            drop_debugger: true,
                            ecma: 6,
                            global_defs: {
                                __UGLIFIED__: true,
                            },
                        },
                        // Required for Element Level CSS, Observable Events, & Android Frame
                        keep_classnames: true,
                        // custom
                        ecma: 6,
                        safari10: platform !== 'android',
                    },
                }),
            ],
        },
        module: {
            rules: [
                {
                    include: join(appFullPath, entryPath),
                    use: [
                        // Require all Android app components
                        platform === 'android' && {
                            loader: '@nativescript/webpack/helpers/android-app-components-loader',
                            options: { modules: appComponents },
                        },

                        {
                            loader: '@nativescript/webpack/bundle-config-loader',
                            options: {
                                angular: true,
                                loadCss: !snapshot, // load the application css if in debug mode
                                unitTesting,
                                appFullPath,
                                projectRoot,
                                ignoredFiles: nsWebpack.getUserDefinedEntries(entries, platform),
                            },
                        },
                    ].filter((loader) => !!loader),
                },

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

                {
                    test: /[\/|\\]app\.css$/,
                    use: [
                        '@nativescript/webpack/helpers/style-hot-loader',
                        {
                            loader: '@nativescript/webpack/helpers/css2json-loader',
                            options: { useForImports: true },
                        },
                    ],
                },
                {
                    test: /[\/|\\]app\.scss$/,
                    use: [
                        '@nativescript/webpack/helpers/style-hot-loader',
                        {
                            loader: '@nativescript/webpack/helpers/css2json-loader',
                            options: { useForImports: true },
                        },
                        '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/webpack/helpers/moduleid-compat-loader', '@nativescript/webpack/helpers/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',
                'global.isAndroid': platform === 'android',
                'global.isIOS': platform === 'ios',
                process: 'global.process',
            }),
            // Remove all files from the out dir.
            new CleanWebpackPlugin({
                cleanOnceBeforeBuildPatterns: itemsToClean,
                verbose: !!verbose,
            }),
            // Copy assets
            new CopyWebpackPlugin([...copyTargets, { from: { glob: '**/*.jpg', dot: false } }, { from: { glob: '**/*.png', dot: false } }], copyIgnore),
            new nsWebpack.GenerateNativeScriptEntryPointsPlugin('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(),
        ],
    };

    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'],
                projectRoot,
                webpackConfig: config,
                snapshotInDocker,
                skipSnapshotTools,
                useLibs,
            })
        );
    }

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

    return config;
};

Describe the bug When I try to run ns run android I get the following error:

C:\Git\aurora-spa>ns run android
Searching for devices...
Preparing project...
Error: Cannot find module '@nativescript/webpack/nativescript-target'
Require stack:
- C:\Git\aurora-spa\webpack.config.js
- C:\Git\aurora-spa\node_modules\@nativescript\webpack\dist\bin\index.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:902:15)
    at Function.Module._load (internal/modules/cjs/loader.js:746:27)
    at Module.require (internal/modules/cjs/loader.js:974:19)
    at require (internal/modules/cjs/helpers.js:92:18)
    at Object.<anonymous> (C:\Git\aurora-spa\webpack.config.js:6:28)
    at Module._compile (internal/modules/cjs/loader.js:1085:14)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
    at Module.load (internal/modules/cjs/loader.js:950:32)
    at Function.Module._load (internal/modules/cjs/loader.js:790:14)
    at Module.require (internal/modules/cjs/loader.js:974:19)
    at require (internal/modules/cjs/helpers.js:92:18)
    at Command.<anonymous> (C:\Git\aurora-spa\node_modules\@nativescript\webpack\dist\bin\index.js:60:25)
    at Command.listener [as _actionHandler] (C:\Git\aurora-spa\node_modules\commander\index.js:922:31)
    at Command._parseCommand (C:\Git\aurora-spa\node_modules\commander\index.js:1503:14)
    at Command._dispatchSubcommand (C:\Git\aurora-spa\node_modules\commander\index.js:1443:18)
    at Command._parseCommand (C:\Git\aurora-spa\node_modules\commander\index.js:1460:12) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    'C:\\Git\\aurora-spa\\webpack.config.js',
    'C:\\Git\\aurora-spa\\node_modules\\@nativescript\\webpack\\dist\\bin\\index.js'
  ]
}
No configuration!
Executing webpack failed with exit code 0.

To Reproduce Run the following command: ns run android.

Expected behavior Runs project on emulator.