Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only vendor.css is being generated when mode is "production". #7791

Closed
sandrocsimas opened this issue Jul 25, 2018 · 9 comments
Closed

Only vendor.css is being generated when mode is "production". #7791

sandrocsimas opened this issue Jul 25, 2018 · 9 comments

Comments

@sandrocsimas
Copy link

Bug report

What is the current behavior?

Only vendor.css is being generated when mode is "production".

If the current behavior is a bug, please provide the steps to reproduce.

When I run Webpack in production mode, only vendor.css bundle is generated. Development mode generates both main.css and vendor.css.
Here is my Webpack configuration:

const webpack = require('webpack');
const CleanPlugin = require('clean-webpack-plugin');
const JsUglifyPlugin = require('uglifyjs-webpack-plugin');
const CssExtractPlugin = require('mini-css-extract-plugin');
const CssOptimizePlugin = require('optimize-css-assets-webpack-plugin');
const CssPurgePlugin = require('purgecss-webpack-plugin');
const HtmlPlugin = require('html-webpack-plugin');
const rxjsPaths = require('rxjs/_esm5/path-mapping');
const path = require('path');
const glob = require('glob');

module.exports = (settings) => {
  function isProduction() {
    return settings.env === 'production';
  }

  const optimization = {
    splitChunks: {
      cacheGroups: {
        vendor: {
          name: 'vendor',
          test: /\/node_modules\//,
          chunks: 'all',
          priority: 0,
          enforce: true,
        },
      },
    },
  };
  if (isProduction()) {
    optimization.minimizer = [
      new JsUglifyPlugin({cache: true, parallel: true}),
      new CssOptimizePlugin({}),
    ];
  }

  return {
    optimization,
    mode: settings.env,
    devtool: isProduction() ? false : 'source-map',
    entry: {
      vendor: path.resolve('client', 'src', 'vendor.ts'),
      main: path.resolve('client', 'src', 'main.ts'),
    },
    output: {
      path: path.resolve('dist'),
      filename: '[name].js',
    },
    resolve: {
      extensions: ['.ts', '.js'],
      modules: [
        path.resolve('client', 'src'),
        path.resolve('node_modules'),
      ],
      alias: rxjsPaths(),
    },
    module: {
      rules: [
        {
          test: /\.ts$/,
          use: ['ts-loader', 'angular2-template-loader'],
          include: path.resolve('client', 'src'),
        },
        {
          test: /\.html$/,
          use: ['html-loader'],
          include: path.resolve('client', 'src'),
        },
        {
          test: /\.css$/,
          use: [CssExtractPlugin.loader, 'css-loader'],
          include: [
            path.resolve('node_modules', 'bootstrap', 'dist', 'css', 'bootstrap.css'),
            path.resolve('node_modules', 'angular-calendar', 'css', 'angular-calendar.css'),
          ],
        },
        {
          test: /\.less$/,
          use: [CssExtractPlugin.loader, 'css-loader', 'less-loader'],
          include: path.resolve('client', 'src', 'assets', 'styles'),
        },
        {
          test: /\.(png|jpe?g|gif|svg|ico)$/,
          use: [{
            loader: 'file-loader',
            options: {
              name: '[path][name].[ext]',
              context: path.resolve('client', 'src'),
            },
          }],
          include: path.resolve('client', 'src', 'assets', 'img'),
        },
        {
          test: /\.(woff(2)?|ttf|otf|eot|svg)$/,
          use: [{
            loader: 'file-loader',
            options: {
              name: '[path][name].[ext]',
              context: path.resolve('client', 'src'),
            },
          }],
          include: path.resolve('client', 'src', 'assets', 'fonts'),
        },
      ],
    },
    plugins: [
      new CleanPlugin(['dist'], {root: path.resolve()}),
      new webpack.optimize.ModuleConcatenationPlugin(),
      new webpack.DefinePlugin({
        'process.env': {
          API_URL: JSON.stringify(settings.apiUrl),
          WEB_URL: JSON.stringify(settings.webUrl),
        },
      }),
      new CssExtractPlugin({filename: 'assets/styles/[name].css'}),
      new CssPurgePlugin({
        paths: glob.sync(`${path.resolve('client', 'src')}/**/*`, {nodir: true}),
        whitelist: ['modal', 'dropdown', 'alert', 'collapse', 'fade', 'show', 'd-block'],
        whitelistPatterns: [/^modal-/, /^dropdown-/, /^alert-/, /^bg-/, /^cal-/],
      }),
      new HtmlPlugin({template: path.resolve('client', 'src', 'index.html')}),
    ],
  };
};

I also commented the lines below to find what plugin is causing this, but the problem persists.

new CssOptimizePlugin({}),
devtool: isProduction() ? false : 'source-map',

I think the problem is this line:

mode: settings.env,

What is the expected behavior?

Bundle main.css should also be generated.

Other relevant information:
webpack version: 4.16.2
Node.js version: v8.10.0
Operating System: Linux (Ubuntu)
Additional tools:

"devDependencies": {
  "angular2-template-loader": "0.6.2",
  "clean-webpack-plugin": "0.1.19",
  "css-loader": "1.0.0",
  "file-loader": "1.1.11",
  "html-loader": "0.5.5",
  "html-webpack-plugin": "3.2.0",
  "less": "3.8.0",
  "less-loader": "4.1.0",
  "mini-css-extract-plugin": "0.4.1",
  "optimize-css-assets-webpack-plugin": "5.0.0",
  "purgecss-webpack-plugin": "1.2.0",
  "release-n-publish": "0.0.6",
  "ts-loader": "4.4.2",
  "webpack": "4.16.2",
  "webpack-cli": "3.1.0",
}
@sandrocsimas
Copy link
Author

sandrocsimas commented Jul 26, 2018

I don't know if this is important but here is the Webpack execution log:

Hash: a7a7daf1fdd9b5397095
Version: webpack 4.16.2
Time: 48009ms
Built at: 2018-07-25 21:50:48
                   Asset       Size  Chunks                    Chunk Names
assets/styles/vendor.css   41.3 KiB       0  [emitted]         vendor
               vendor.js   5.45 MiB       0  [emitted]  [big]  vendor
                 main.js    385 KiB       1  [emitted]  [big]  main
              index.html  523 bytes          [emitted]         
Entrypoint main [big] = assets/styles/vendor.css vendor.js main.js
  [8] ./node_modules/@ng-bootstrap/ng-bootstrap/modal/modal.module.js + 6 modules 18.3 KiB {0} [built]
      |    7 modules
 [22] ./node_modules/@angular/router/fesm5/router.js + 11 modules 222 KiB {0} [built]
      |    12 modules
[145] ./node_modules/@ng-bootstrap/ng-bootstrap/datepicker/datepicker.module.js + 20 modules 103 KiB {0} [built]
      |    21 modules
[146] ./node_modules/angular-calendar/fesm5/angular-calendar.js + 13 modules 449 KiB {0} [built]
      |    14 modules
[215] (webpack)/buildin/global.js 489 bytes {0} [built]
[264] ./node_modules/@angular/core/fesm5 lazy namespace object 160 bytes {1} [built]
[446] ./node_modules/@ng-bootstrap/ng-bootstrap/timepicker/timepicker.module.js + 4 modules 18 KiB {0} [built]
      |    5 modules
[447] ./node_modules/@ng-bootstrap/ng-bootstrap/popover/popover.module.js + 3 modules 13 KiB {0} [built]
      |    4 modules
[449] ./node_modules/@ng-bootstrap/ng-bootstrap/dropdown/dropdown.module.js + 2 modules 11.4 KiB {0} [built]
      |    3 modules
[450] ./node_modules/@ng-bootstrap/ng-bootstrap/alert/alert.module.js + 2 modules 2.93 KiB {0} [built]
      |    3 modules
[451] ./node_modules/@angular/platform-browser-dynamic/fesm5/platform-browser-dynamic.js + 1 modules 1.08 MiB {0} [built]
      |    2 modules
[452] ./node_modules/ngx-clipboard/fesm5/ngx-clipboard.js + 1 modules 25.7 KiB {0} [built]
      |    2 modules
[704] ./client/src/main.ts + 71 modules 202 KiB {1} [built]
      | ./client/src/app/services/task.service.ts 3.76 KiB [built]
      | ./client/src/main.ts 968 bytes [built]
      | ./client/src/app/utils/angular.utils.ts 5.28 KiB [built]
      | ./client/src/app/services/account.service.ts 4.96 KiB [built]
      | ./client/src/app/services/alert.service.ts 2.03 KiB [built]
      | ./client/src/app/app.component.ts 1.28 KiB [built]
      | ./client/src/app/app.routes.ts 2.63 KiB [built]
      | ./client/src/app/app.module.ts 11.1 KiB [built]
      | ./client/src/app/services/company.service.ts 10.8 KiB [built]
      | ./client/src/app/services/payment.service.ts 3.11 KiB [built]
      | ./client/src/app/services/event.service.ts 1.52 KiB [built]
      | ./client/src/app/services/client.service.ts 6.97 KiB [built]
      | ./client/src/app/services/plan.service.ts 3.45 KiB [built]
      | ./client/src/app/services/token.service.ts 2.51 KiB [built]
      | ./client/src/app/utils/constants.ts 1.33 KiB [built]
      |     + 57 hidden modules
[706] ./client/src/assets/styles/main.less 39 bytes [built]
[707] ./client/src/vendor.ts 95 bytes {0} [built]
    + 817 hidden modules

Main.less appears here:

[706] ./client/src/assets/styles/main.less 39 bytes [built]

Searching for 706 in the dist folder this is the result:

/***/ }),
/* 706 */,
/* 707 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

Looking at the json generated with --stats I found this:

{
    "id": 706,
    "identifier": "/home/sandro/workspace/intercambio-website/node_modules/mini-css-extract-plugin/dist/loader.js!/home/sandro/workspace/intercambio-website/node_modules/css-loader/i
ndex.js!/home/sandro/workspace/intercambio-website/node_modules/less-loader/dist/cjs.js!/home/sandro/workspace/intercambio-website/client/src/assets/styles/main.less",
    "name": "./client/src/assets/styles/main.less",
    ...
    "depth": 1,
    "source": "// extracted by mini-css-extract-plugin"
 },

It seems the css was extracted by mini-css-extract-plugin, but the bundle is not saved. =(

@sandrocsimas
Copy link
Author

I created this repository reproducing the error:
https://github.com/sandrocsimas/webpack-bug

@Legends
Copy link
Member

Legends commented Jul 27, 2018

Besides your problem, vendor.ts is not an entry point and is therefore not allowed under entry when using webpack 4.
This was possible till webpack 3 only.

@Legends
Copy link
Member

Legends commented Jul 28, 2018

Tried adding:

 "sideEffects": [
    "./client/src/assets/styles/main.less"
  ],

While this generates the main.css file, somehow it only contains one style rule:

#d {
  display: block;
}

@sandrocsimas
Copy link
Author

sandrocsimas commented Jul 28, 2018

Thanks @Legend, why vendor.ts is not an entry point? Where cam I read more about this?
I tried adding main.less to sideEffects and it worked. Don't know if this is the real solution for the problem. Let's keep the issue opened to see if there's another solution in the webpack config.

@Legends
Copy link
Member

Legends commented Jul 28, 2018

Can't find it, it's buried somewhere.

wp4 create a dependency graph out of your entry-point(s). An entry point is a real entry to your application.
For example in a SPA app you would usually have only one entry-point and in a MPA app many entry points.

And in your entry-point you import other modules/vendor modules which in turn again import some other modules, etc....

webpack then creates optimized bundles out of your entry points.

@sandrocsimas
Copy link
Author

sandrocsimas commented Jul 28, 2018

Even with just one entry, the main.less is not generated unless I add it to sideEffects. =(

@Legends
Copy link
Member

Legends commented Jul 28, 2018

I didn't say that it doesn't render main.less because of having vendor.ts under entry.

In general I would do:

package.json:

"sideEffects": [
    "*.less",
    "*.css"
  ],

Otherwise it can happen that your css/less files are treeshaked in --mode production

@sandrocsimas
Copy link
Author

Thanks @Legends! Problem solved by adding less and css to sideEffects.

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

No branches or pull requests

2 participants