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!
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.