Closed gaterking closed 6 years ago
Mini-css-extract-plugin is using _compilation
from loaderContext
. A HappyFakeCompilation
will need to be made and added to HappyFakeLoaderContext
. It looks like it is only using _compilation
to get the webpack config or more specifically the publicPath
and it uses the method createChildCompiler
.
Edit:
I'm not sure if the above would work (or be a reasonable solution.) If we make a config that is more similar to the extract-text-webpack-plugin
example then we get an option that works :smiley:. It would seem that we don't want to run mini-css-extract-plugin
with multi-threading. Instead we run it on the main thread like so
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HappyPack = require('happypack');
const happyThreadPool = HappyPack.ThreadPool({ size: 5 });
module.exports = {
mode: 'production',
devtool: false,
context: path.resolve(__dirname),
entry: {
css: './test.css',
scss: './test.scss'
},
output: {
path: path.resolve('./dist'),
filename: '[name].js'
},
module: {
rules: [
{
test: /\.scss$/,
loaders: [
MiniCssExtractPlugin.loader,
'happypack/loader?id=scss',
]
},
{
test: /\.css$/,
loaders: [
MiniCssExtractPlugin.loader,
'happypack/loader?id=css',
]
},
]
},
plugins: [
new HappyPack({
id: 'scss',
threadPool: happyThreadPool,
loaders: [
{
loader: 'css-loader',
options: {
minimize: true,
sourceMap: false
}
},
{
loader: 'postcss-loader',
options: {
indent: 'postcss',
plugins: (loader) => [
require('autoprefixer')()
],
sourceMap: false
}
},
{
loader: 'sass-loader',
options: {
sourceMap: false
}
}
]
}),
new HappyPack({
id: 'css',
threadPool: happyThreadPool,
loaders: [
{
loader: 'css-loader',
options: {
minimize: true,
sourceMap: false
}
},
{
loader: 'postcss-loader',
options: {
plugins: (loader) => [
require('autoprefixer')()
],
sourceMap: false
}
}
]
}),
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
],
}
It work well for .js and .css. But in my project, I use vue-loader v15-rc.2. I think it is the error created by vue-style-loader. @yyx990803 may see these.
error detail:
Module build failed: CssSyntaxError: ****\components\win-prize-board.vue:1:1: Unknown word
> 1 | // extracted by mini-css-extract-plugin
| ^
at Input.error (E:\****\****\mobile\node_modules\postcss\lib\input.es6:94:22)
at Parser.unknownWord (E:\****\****\mobile\node_modules\postcss\lib\parser.es6:486:26)
at Parser.other (E:\****\****\mobile\node_modules\postcss\lib\parser.es6:150:18)
at Parser.parse (E:\****\****\mobile\node_modules\postcss\lib\parser.es6:58:22)
at parse (E:\****\****\mobile\node_modules\postcss\lib\parse.es6:13:16)
at new LazyResult (E:\****\****\mobile\node_modules\postcss\lib\lazy-result.es6:42:24)
at Processor.process (E:\****\****\mobile\node_modules\postcss\lib\processor.es6:95:16)
at compileStyle (E:\****\****\mobile\node_modules\@vue\component-compiler-utils\dist\compileStyle.js:29:35)
at Object.module.exports (E:\****\****\mobile\node_modules\vue-loader\lib\loaders\stylePostLoader.js:9:33)
rule:
{
test: /\.scss$/,
loaders: [MiniCssExtractPlugin.loader,
// 'vue-style-loader',
'happypack/loader?id=scss'],
}
new HappyPack({
id: 'scss',
threadPool: happyThreadPool,
loaders: [
// 'vue-style-loader',
{
loader: 'css-loader',
options: {
minimize: true,
sourceMap: false
}
}, {
loader: 'sass-loader',
options: {
minimize: true,
sourceMap: false
}
}]
})
You will want to choose vue-style-loader
or MiniCssExtractPlugin
. The vue-style-loader
should be put in the happypack loaders option. However, I don't believe happypack
supports vue-loader@next
.
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HappyPack = require('happypack');
const { VueLoaderPlugin } = require('vue-loader')
const happyThreadPool = HappyPack.ThreadPool({ size: 5 });
module.exports = {
mode: 'production',
devtool: false,
context: path.resolve(__dirname),
entry: {
css: './testcss.js',
scss: './testscss.js',
vue: './test.vue'
},
output: {
path: path.resolve('./dist'),
filename: '[name].js'
},
module: {
rules: [
{
test: /\.vue$/,
loaders: 'happypack/loader?id=vue'
},
{
test: /\.scss$/,
loaders: [
// MiniCssExtractPlugin.loader,
'happypack/loader?id=scss'
]
},
{
test: /\.css$/,
loaders: [
// MiniCssExtractPlugin.loader,
'happypack/loader?id=css'
]
},
]
},
plugins: [
new HappyPack({
id: 'scss',
threadPool: happyThreadPool,
loaders: [
'vue-style-loader',
{
loader: 'css-loader',
options: {
minimize: true,
sourceMap: false
}
},
{
loader: 'postcss-loader',
options: {
plugins: (loader) => [
require('autoprefixer')()
],
sourceMap: false
}
},
{
loader: 'sass-loader',
options: {
sourceMap: false
}
}
]
}),
new HappyPack({
id: 'css',
threadPool: happyThreadPool,
loaders: [
'vue-style-loader',
{
loader: 'css-loader',
options: {
minimize: true,
sourceMap: false
}
},
{
loader: 'postcss-loader',
options: {
plugins: (loader) => [
require('autoprefixer')()
],
sourceMap: false
}
}
]
}),
new HappyPack({
id: 'vue',
threadPool: happyThreadPool,
loaders: ['vue-loader']
}),
new VueLoaderPlugin(),
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
],
}
When I run this config, the VueLoaderPlugin
cannot find vue-loader
in the module rules because it is defined in HappyPack
loader options. If I put vue-loader in module rules I get different errors. You may have to use vue-loader@14.x.x
and this adapter in the extractCSS
vue-loader options.
class MiniCssAdapter extends MiniCssExtractPlugin {
static extract(options) {
const rawLoaders = options.use || options;
const loaders = typeof rawLoaders === 'string' ? rawLoaders.split('!') : rawLoaders;
return [this.loader].concat(loaders);
}
}
...
extractCSS: MiniCssAdapter
Thanks @henopied for helping and @gaterking for reporting. Generally, any loader that relies on a plugin won't work since we can't serialize the plugins across to the background threads.
The only way to work around that (as in the case of postcss-loader
) is to have the "plugins" instantiated in the background threads themselves, e.g. by a config file that gets required by the loader (in which case you only pass the path to that file as an option to that loader.) But in this case I don't know if that's viable since VueLoaderPlugin
may be doing things that require access to webpack and thus has to be in the foreground thread.
If it's significant enough to support, we need to look at the implementation of that plugin and see what kind of APIs it's relying on.
vuejs/vue-loader#1273 vue-loader 15 not suppport happypack
When I use happypack with MiniCssExtractPlugin, it throw error as bellow. If I remove happypack, it work well. webpack 4.5.0 happypack 5.0.0-beta.3 mini-css-extract-plugin 0.4.0
rules
plugins: