NativeScript / nativescript-dev-webpack

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

--bundle option ignores app.scss file #473

Closed RadouaneRoufid closed 5 years ago

RadouaneRoufid commented 6 years ago

Issue Checklist

Tell us about the problem

Applying a --bundle option makes the application lose its css. Everything is ok when the command is run without --bundle.

Local environment

Project data

app.component.ts

@Component({
    moduleId: module.id,
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.scss'] // I tried to delete this line but in vain
})
export class AppComponent implements OnInit, OnDestroy 

app.android.scss

@import './app-variables'; // I also tried '~/app-variables'
@import '~nativescript-theme-core/scss/index';
@import '~nativescript-theme-core/scss/platforms/index.android';

@import './app-common';

package.json

"dependencies": {
    "@angular/animations": "~5.2.1",
    "@angular/common": "^5.2.1",
    "@angular/compiler": "^5.2.1",
    "@angular/core": "^5.2.1",
    "@angular/forms": "^5.2.1",
    "@angular/http": "^5.2.1",
    "@angular/platform-browser": "^5.1.0",
    "@angular/platform-browser-dynamic": "^5.2.1",
    "@angular/router": "^5.2.1",
    "@ngrx/effects": "^4.1.1",
    "@ngrx/router-store": "^4.1.1",
    "@ngrx/store": "^4.1.1",
    "@ngrx/store-devtools": "^4.1.1",
    "@ngx-progressbar/core": "^3.0.1",
    "@ngx-progressbar/http-client": "^3.0.1",
    "@ngx-translate/core": "^6.0.1",
    "@ngx-translate/http-loader": "0.0.3",
    "arrive": "^2.3.1",
    "bootstrap": "4.0.0-alpha.6",
    "bootstrap-datepicker": "1.6.4",
    "bootstrap-social": "^5.1.1",
    "core-js": "^2.5.2",
    "font-awesome": "4.7.0",
    "fs": "0.0.1-security",
    "hammerjs": "^2.0.8",
    "i": "^0.3.6",
    "lodash": "^4.17.4",
    "materialize-css": "0.100.2",
    "nativescript-angular": "^5.2.0",
    "nativescript-background-http": "^3.2.0",
    "nativescript-bottom-navigation": "^1.1.2",
    "nativescript-bottombar": "^3.0.8",
    "nativescript-cardview": "^2.0.5",
    "nativescript-checkbox": "^3.0.3",
    "nativescript-floatingactionbutton": "^4.1.3",
    "nativescript-fresco": "^3.0.2",
    "nativescript-google-maps-sdk": "^2.5.0",
    "nativescript-imagepicker": "^5.0.0",
    "nativescript-localstorage": "^1.1.5",
    "nativescript-mediafilepicker": "^1.0.5",
    "nativescript-modal-datetimepicker": "^1.1.0",
    "nativescript-ng-shadow": "^2.1.0",
    "nativescript-oauth": "^2.0.1",
    "nativescript-phone": "^1.3.1",
    "nativescript-photoviewer": "^1.4.0",
    "nativescript-pro-ui": "^3.4.0-2018-1-9-3",
    "nativescript-snackbar": "^2.0.0",
    "nativescript-theme-core": "~1.0.2",
    "ng2-validation": "^4.2.0",
    "ngrx-store-freeze": "^0.1.9",
    "ngx-pagination": "^3.0.3",
    "npm": "^4.2.0",
    "osenv": "^0.1.4",
    "path": "^0.12.7",
    "reflect-metadata": "^0.1.12",
    "rxjs": "^5.5.5",
    "tether": "^1.4.3",
    "tns-core-modules": "^3.4.1",
    "url": "^0.11.0",
    "velocity-animate": "^1.5.1",
    "zone.js": "0.8.5"
  },
  "devDependencies": {
    "@angular/compiler-cli": "^5.2.1",
    "@ngtools/webpack": "~1.9.4",
    "@types/googlemaps": "^3.30.8",
    "@types/jasmine": "^2.8.5",
    "babel-traverse": "6.25.0",
    "babel-types": "6.25.0",
    "babylon": "6.17.4",
    "copy-webpack-plugin": "~4.3.0",
    "cross-env": "^5.1.3",
    "css-loader": "~0.28.7",
    "del": "^2.2.2",
    "extract-text-webpack-plugin": "~3.0.2",
    "gulp": "^4.0.0",
    "gulp-debug": "^3.1.0",
    "gulp-exec": "^3.0.1",
    "gulp-rename": "^1.2.2",
    "gulp-spawn": "^0.4.0",
    "gulp-string-replace": "^0.4.0",
    "lazy": "1.0.11",
    "mkdirp": "^0.5.1",
    "nativescript-css-loader": "~0.26.1",
    "nativescript-dev-android-snapshot": "^0.*.*",
    "nativescript-dev-sass": "^1.4.0",
    "nativescript-dev-typescript": "~0.6.0",
    "nativescript-dev-webpack": "^0.9.2",
    "nativescript-worker-loader": "~0.8.1",
    "raw-loader": "~0.5.1",
    "resolve-url-loader": "~2.2.1",
    "run-sequence": "^2.2.1",
    "sass-loader": "~6.0.6",
    "tns-platform-declarations": "^3.4.1",
    "typescript": "^2.4.0",
    "typescript-register": "^1.1.0",
    "uglifyjs-webpack-plugin": "~1.1.6",
    "webpack": "~3.10.0",
    "webpack-bundle-analyzer": "^2.9.1",
    "webpack-sources": "~1.1.0"
  }

const webpack = require("webpack"); const nsWebpack = require("nativescript-dev-webpack"); const nativescriptTarget = require("nativescript-dev-webpack/nativescript-target"); const CopyWebpackPlugin = require("copy-webpack-plugin"); const ExtractTextPlugin = require("extract-text-webpack-plugin"); const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer"); const { NativeScriptWorkerPlugin } = require("nativescript-worker-loader/NativeScriptWorkerPlugin"); const UglifyJsPlugin = require("uglifyjs-webpack-plugin");

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 platforms = ["ios", "android"]; const { snapshot, uglify, report, aot } = env; const ngToolsWebpackOptions = { tsConfigPath: "tsconfig.json" };

const config = {
    context: resolve("./app"),
    target: nativescriptTarget,
    entry: {
        bundle: aot ? "./main.aot.ts" : "./main.ts",
        vendor: "./vendor",
    },
    output: {
        pathinfo: true,
        // Default destination inside platforms/<platform>/...
        path: resolve(nsWebpack.getAppPath(platform)),
        libraryTarget: "commonjs2",
        filename: "[name].js",
    },
    resolve: {
        extensions: [".ts", ".js", ".scss", ".css"],
        // Resolve {N} system modules from tns-core-modules
        modules: [
            "node_modules/tns-core-modules",
            "node_modules",
        ],
        alias: {
            '~': resolve("./app")
        },
        // don't resolve symlinks to symlinked modules
        symlinks: false
    },
    resolveLoader: {
        // don't resolve symlinks to symlinked loaders
        symlinks: false
    },
    node: {
        // Disable node shims that conflict with NativeScript
        "http": false,
        "timers": false,
        "setImmediate": false,
        "fs": "empty",
    },
    module: {
        rules: [
            { 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",
                { loader: "@ngtools/webpack", options: ngToolsWebpackOptions },
            ]},
        ],
    },
    plugins: [
        // Vendor libs go to the vendor.js chunk
        new webpack.optimize.CommonsChunkPlugin({
            name: ["vendor"],
        }),
        // Define useful constants like TNS_WEBPACK
        new webpack.DefinePlugin({
            "global.TNS_WEBPACK": "true",
        }),
        // Copy assets to out dir. Add your own globs as needed.
        new CopyWebpackPlugin([
            { from: "App_Resources/**" },
            { from: "fonts/**" },
            { from: "**/*.jpg" },
            { from: "**/*.png" },
            { from: "**/*.xml" },
        ]),
        // Generate a bundle starter script and activate it in package.json
        new nsWebpack.GenerateBundleStarterPlugin([
            "./vendor",
            "./bundle",
        ]),
        // Support for web workers since v3.2
        new NativeScriptWorkerPlugin(),
        // AngularCompilerPlugin with augmented NativeScript filesystem to handle platform specific resource resolution.
        new nsWebpack.NativeScriptAngularCompilerPlugin(
            Object.assign({
                entryModule: resolve(__dirname, "app/native.module#AppModule"),
                skipCodeGeneration: !aot,
                platformOptions: {
                    platform,
                    platforms,
                    // ignore: ["App_Resources"]
                },
            }, ngToolsWebpackOptions)
        ),
        // 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: join(__dirname, "report", `report.html`),
        statsFilename: join(__dirname, "report", `stats.json`),
    }));
}
if (snapshot) {
    config.plugins.push(new nsWebpack.NativeScriptSnapshotPlugin({
        chunk: "vendor",
        projectRoot: __dirname,
        webpackConfig: config,
        targetArchs: ["arm", "arm64", "ia32"],
        tnsJavaClassesOptions: { packages: ["tns-core-modules" ] },
        useLibs: false
    }));
}
if (uglify) {
    config.plugins.push(new webpack.LoaderOptionsPlugin({ minimize: true }));

    // Work around an Android issue by setting compress = false
    const compress = platform !== "android";
    config.plugins.push(new UglifyJsPlugin({
        uglifyOptions: {
            mangle: { reserved: nsWebpack.uglifyMangleExcludes },
            compress,
        }
    }));
}
return config;

};



Command executed : tns run android --bundle --device avd27

[NativeScript Forum]: http://forum.nativescript.org
[issues]: https://github.com/nativescript/nativescript-dev-webpack/issues?utf8=✓&q=is%3Aissue
[demo apps]: ../demo
[documentation]: https://docs.nativescript.org/best-practices/bundling-with-webpack
RadouaneRoufid commented 6 years ago

any suggestions to this ?

RadouaneRoufid commented 6 years ago

I had to do this as a possible workaround :

webpack.config.js

Declaring the main sheet

let mainSheet;
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 platforms = ["ios", "android"];
    const { snapshot, uglify, report, aot } = env;
    const ngToolsWebpackOptions = { tsConfigPath: "tsconfig.json" };

    mainSheet = `app.${platform}.css`;

    const config = {
        context: resolve("./app"),
        target: nativescriptTarget,
        entry: {
            bundle: aot ? "./main.aot.ts" : "./main.ts",
            vendor: "./vendor",
            [mainSheet]: `./${mainSheet}`,
        },
...

nativescript-dev-sass/lib/before-prepare.js

I had to modify this file, to allow scss file to be compiled when --bundle option is active.

var converter = require('./converter');

module.exports = function ($logger, $projectData, $usbLiveSyncService) {
    var liveSync = $usbLiveSyncService.isInitialized;
    var bundle = $projectData.$options.bundle;
    if (liveSync) {
        $logger.warn("Hook skipped because either bundling or livesync is in progress.")
        return;
    }

    return converter.convert($logger, $projectData.projectDir, $projectData.appDirectoryPath);
}

Style is now picked and applied.

leocrawf commented 6 years ago

This fixed my css issue with webpack. Thank you so much.

exeleon commented 6 years ago

I have nativescript-dev-webpack 0.9.2 and this problem was related with #298 . I replaced my imports with "~/" to "./" and works perfectly with --bundle.

RadouaneRoufid commented 6 years ago

Still having the issue with "nativescript-dev-webpack": "^0.10.1",

leocrawf commented 6 years ago

I am not sure but I all works now. I removed the modification above and it still works as expected.

RoyiNamir commented 6 years ago

@RadouaneRoufid Hi. Have you met this problem ? (similar)

RadouaneRoufid commented 6 years ago

Have you tried to set mainSheet in entry in webpack.config.js ?

entry: {
            bundle: aot ? "./main.aot.ts" : "./main.ts",
            vendor: "./vendor",
            [mainSheet]: `./app1.css`,
        },
RoyiNamir commented 6 years ago

@RadouaneRoufid Thanks for response. it's a brand new empty project ( via tns create ddd --ng). All I want is that app1.css will be the global css - not the app.css (becuase in the real scenario we need to apply different css files accordigng to language).

main.aot.ts

image

main.ts :

image

webpack :

image

with --bundle I see the app eventually running but with error :

image

With uglify , it is stuck forever on this error :

image

This is the demo empty project i'm using : https://ufile.io/x1ilb

it's a completly empty project...

RadouaneRoufid commented 6 years ago

Just a little question ?

The css file selection is done just at build time ? Or dynamically at runtime ?

RoyiNamir commented 6 years ago

@RadouaneRoufid in runtime. Think of it as if the user changed preferd language in the app and it is saved in applican settings And next time the app is on we should apply the right css (each css file has different font file which is the main reason for this whole thing)

RadouaneRoufid commented 6 years ago

Correct me if I'm wrong but is seems like you address a build time problem which has not be the case. If you let app.css file and try to uply your logic in your custom Activity

class ActivityAndroid extends android.support.v7.app.AppCompatActivity {
    protected onStart(): void {
// Apply custom logic to apply css here or in OnCreate lifecycle ??
        this._callbacks.onStart(this, super.onStart);
    }
}

Any way your error seems to be a import problem. Try relative path to app instead of tild one ~/app

RoyiNamir commented 6 years ago

@RadouaneRoufid i never used any ~/app in my code.

The build shows error with bundle but runs ok

The build shiws error and stuck with uglify

RadouaneRoufid commented 6 years ago

Okay, your problem is that when bundling, load-application-css.js will try to load ~/app.* which does not exist in your case.

../node_modules/nativescript-dev-webpack/load-application-css.js
const appCssContext = require.context("~/", false, /^\.\/app\.(css|scss|less|sass)$/);

You will have to create an empty app.css or modify this file or find another approach to address your need !

mikaelkalt commented 6 years ago

We're facing more or less the same problem. Since --bundle ignores sass compilation our CI build fails, because non of the css files we're referencing from the components are available.

Is there a workaround for that? I don't really understand why sass compilation is disabled for bundling? Can we somehow trigger this hook manually before?

I've created a sample project to demonstrate the problem: https://github.com/mikaelkalt/nativescript-angular-sass-webpack-sample

marklanhamhc commented 5 years ago

Yeah I'm having the same problem. I'm using Nativescript with Angular but when I try and run $ tns build ios --bundle using Webpack (following these instructions: https://docs.nativescript.org/angular/performance-optimizations/bundling-with-webpack) I just get the error:

File to import not found or unreadable: ~/app-variables.

mhmo91 commented 5 years ago

any updates here?

marklanhamhc commented 5 years ago

Managed to sort my issue, it turns out the path WAS incorrect, you can’t use a tilde ~ you have to use a relative path, for example './../../app-variables'

miroslavaivanova commented 5 years ago

I'm closing this issue as it should be working now.