2

Not sure if this is a bug or just my setup, I am using the CommonsChunkPlugin to get a separate common.js for three entry points in my project, and using the extract-text-webpack-plugin to get the css files. My entry points are app, login and register. I am able to get:

app.js
app.vendor.js
login.js
register.js
common.js

For css:

app.css 
register.css
login.css

I can't seem to get common.css generated. All the css gets crammed into a single app.css file.

My project is setup based on the vuetify webpack template: https://github.com/vuetifyjs/webpack-advanced

Here is my config:

3 entry points:

module.exports = {
  entry: {
    app: './src/main.js',
    login: './src/Login/login.js',
    register: './src/Register/register.js'
 },

The plugins - I have HtmlWebpackPlugin for each entry point (showing only one):

new HtmlWebpackPlugin({
  filename: process.env.NODE_ENV === 'testing'
    ? 'index.html'
    : config.build.index,
  template: 'index.html',
  inject: false,
  hash: true,
  minify: {
    removeComments: true,
    collapseWhitespace: true,
    removeAttributeQuotes: false,
    minifyJS: true
  },
  chunksSortMode: appChunkOrder
}),

Common chunks:

new webpack.optimize.CommonsChunkPlugin({
  name: 'app.vendor',
  chunks: ['app'],
  minChunks: isVendor,
}),    
new webpack.optimize.CommonsChunkPlugin({
  name: 'login.vendor',
  chunks: ['login'],
  minChunks: isVendor,
}),
new webpack.optimize.CommonsChunkPlugin({
  name: 'register.vendor',
  chunks: ['register'],
  minChunks: isVendor,
}),    
// Extract chunks common to both app and login
new webpack.optimize.CommonsChunkPlugin({
  name: 'common',
  chunks: ['app.vendor', 'login.vendor', 'register.vendor', 'app', 'login', 'register'],
  minChunks: (module, count) => count >= 2 && isVendor(module),
}),

The full config:

plugins: [
new webpack.DefinePlugin({'process.env': env }),
new webpack.optimize.UglifyJsPlugin({
  compress: {
    warnings: false
  },
  sourceMap: true
}),
// extract css into its own file
new ExtractTextPlugin({
  filename: utils.assetsPath('css/[name].[contenthash].css')
}),
new OptimizeCSSPlugin({
  cssProcessorOptions: {
    safe: true
  }
}),
// generate Html index files for 3 entries:
new HtmlWebpackPlugin({
  filename: process.env.NODE_ENV === 'testing'
    ? 'index.html'
    : config.build.index,
  template: 'index.html',
  inject: false,
  hash: true,
  minify: {
    removeComments: true,
    collapseWhitespace: true,
    removeAttributeQuotes: false,
    minifyJS: true
  },
  chunksSortMode: appChunkOrder
}),
new HtmlWebpackPlugin({
  filename: process.env.NODE_ENV === 'testing'
    ? 'src/Login/login.html'
    : config.build.login,
  template: 'src/Login/login.html',
  inject: false,
  hash: true,
  minify: false,
  chunksSortMode: loginChunkOrder
}),
new HtmlWebpackPlugin({
  filename: process.env.NODE_ENV === 'testing'
    ? 'src/Register/register.html'
    : config.build.register,
  template: 'src/Register/register.html',
  inject: false,
  hash: true,
  minify: false,
  chunksSortMode: registerChunkOrder
}),    
// Chunks:
new webpack.optimize.CommonsChunkPlugin({
  name: 'app.vendor',
  chunks: ['app'],
  minChunks: isVendor,
}),    
new webpack.optimize.CommonsChunkPlugin({
  name: 'login.vendor',
  chunks: ['login'],
  minChunks: isVendor,
}),
new webpack.optimize.CommonsChunkPlugin({
  name: 'register.vendor',
  chunks: ['register'],
  minChunks: isVendor,
}),    
// Extract chunks common to both app and login
new webpack.optimize.CommonsChunkPlugin({
  name: 'common',
  chunks: ['app.vendor', 'login.vendor', 'register.vendor', 'app', 'login', 'register'],
  minChunks: (module, count) => count >= 2 && isVendor(module),
}),
// copy custom static assets
new CopyWebpackPlugin([
  {
    from: path.resolve(__dirname, '../static'),
    to: config.build.assetsSubDirectory,
    ignore: ['.*']
  }
])

Any help appreciated!

JerryH
  • 115
  • 2
  • 14

1 Answers1

2

I have a very similar setup and managed to get it working. For me, the crucial part was to import common styles in .js files instead of in .scss files.

Here's my project in a nutshell:

common/
  main.scss    <-- common styles
app/
  index.js
  main.scss    <-- styles specific for app
admin/
  index.js
  main.scss    <-- styles specific for admin
registration/
  index.js
  main.scss    <-- styles specific for registration
base.html
webpack.config.js

app/index.js:

import '../common/main'   // <-- this did the trick!
import './main'

// some js...

Both admin/index.js and registration/index.js are very similar.


webpack.config.js (only important parts, using some ES6 syntax):

const entries = {
  app: 'app/index.js',
  admin: 'admin/index.js'
  registration: 'registration/index.js',
};

const commonChunks = [
  'vendor',
  'common',
];

function isVendor(module) {
  if (typeof module.context !== 'string') {
    return false;
  }
  return module.context.indexOf('node_modules') !== -1;
}

export default {
  entry: {...entries},

  // ...

  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: 'common',
      filename: '[name].bundle.js',
      minChunks: 2
    }),

    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      filename: '[name].bundle.js',
      chunks: [...Object.keys(entries), 'common'],
      minChunks: function(module) {
        return isVendor(module);
      }
    }),

    new ExtractTextPlugin({
      filename: '[name].bundle.css'
    }),

    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, 'base.html'),
      filename: 'app.html',
      chunks: [...commonChunks, 'app'],
      chunksSortMode: 'manual'
    }),

    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, 'base.html'),
      filename: 'admin.html',
      chunks: [...commonChunks, 'admin'],
      chunksSortMode: 'manual'
    }),

    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, 'base.html'),
      filename: 'registration.html',
      chunks: [...commonChunks, 'registration'],
      chunksSortMode: 'manual'
    })
  ]
};

My initial approach was to import common/main.scss in other .scss files, e.g.

app/main.scss:

@import '../common/main'

// styles specific for app

but that didn't work and I came up with the solution above.

Also, adding chunksSortMode: 'manual' was required in my case as the HtmlWebpackPlugin was sometimes including scripts in the wrong order.

pawel
  • 513
  • 8
  • 15
  • Thanks very much for your reply! I am importing third party packages like: `import Vuetify from 'vuetify'`, I don't know how css files are handled in this case - do I need to import them separately? – JerryH Oct 23 '17 at 05:05
  • I am hoping the css that comes with third party libraries can be separated out. But I'm not importing them directly by file name... – JerryH Oct 23 '17 at 05:08