UNPKG

3.6 kBJavaScriptView Raw
1const ExtractTextPlugin = require('extract-text-webpack-plugin');
2const merge = require('deepmerge');
3
4module.exports = (neutrino, opts = {}) => {
5 const modules = opts.modules || true;
6 const modulesTest = opts.modulesTest || neutrino.regexFromExtensions(['module.css']);
7 const options = merge({
8 test: neutrino.regexFromExtensions(['css']),
9 ruleId: 'style',
10 styleUseId: 'style',
11 cssUseId: 'css',
12 css: {
13 importLoaders: opts.loaders ? opts.loaders.length : 0
14 },
15 style: {},
16 hot: true,
17 hotUseId: 'hot',
18 modules,
19 modulesTest,
20 modulesSuffix: '-modules',
21 exclude: modules && modulesTest,
22 loaders: [],
23 extractId: 'extract',
24 extract: {
25 plugin: {
26 filename: neutrino.options.command === 'build' ? '[name].[contenthash].css' : '[name].css',
27 ignoreOrder: opts.modules !== false,
28 allChunks: true
29 }
30 }
31 }, opts);
32
33 const rules = [options];
34
35 if (options.modules) {
36 rules.push(
37 merge(options, {
38 test: options.modulesTest,
39 exclude: options.modulesExclude,
40 ruleId: `${options.ruleId}${options.modulesSuffix}`,
41 styleUseId: `${options.styleUseId}${options.modulesSuffix}`,
42 cssUseId: `${options.cssUseId}${options.modulesSuffix}`,
43 hotUseId: `${options.hotUseId}${options.modulesSuffix}`,
44 extractId: `${options.extractId}${options.modulesSuffix}`,
45 css: {
46 modules: options.modules
47 }
48 })
49 );
50 };
51
52 rules.forEach(options => {
53 const styleRule = neutrino.config.module.rule(options.ruleId);
54 const loaders = [
55 {
56 loader: require.resolve('style-loader'),
57 options: options.style,
58 useId: options.styleUseId
59 },
60 {
61 loader: require.resolve('css-loader'),
62 options: options.css,
63 useId: options.cssUseId
64 },
65 ...options.loaders
66 ]
67 .map((loader, index) => {
68 const obj = typeof loader === 'object' ? loader : { loader };
69
70 return Object.assign(obj, {
71 useId: obj.useId || `${options.cssUseId}-${index}`
72 });
73 });
74
75 loaders.forEach(loader => {
76 styleRule
77 .test(options.test)
78 .when(options.exclude, rule => rule.exclude.add(options.exclude))
79 .use(loader.useId)
80 .loader(loader.loader)
81 .when(loader.options, use => use.options(loader.options));
82 });
83
84 if (options.extract) {
85 const styleEntries = styleRule.uses.entries();
86 const useIds = Object.keys(styleEntries).filter(key => key !== options.styleUseId);
87 const extractLoader = Object.assign({
88 use: useIds.map(key => ({
89 loader: styleEntries[key].get('loader'),
90 options: styleEntries[key].get('options')
91 })),
92 fallback: {
93 loader: styleEntries[options.styleUseId].get('loader'),
94 options: styleEntries[options.styleUseId].get('options')
95 }
96 }, options.extract.loader || {});
97
98 styleRule
99 .uses
100 .clear()
101 .end()
102 .when(options.hot, (rule) => {
103 rule.use(options.hotUseId)
104 .loader(require.resolve('css-hot-loader'))
105 .when(options.hot !== true, use => use.options(options.hot));
106 });
107
108 ExtractTextPlugin
109 .extract(extractLoader)
110 .forEach(({ loader, options }) => {
111 styleRule
112 .use(loader)
113 .loader(loader)
114 .options(options);
115 });
116
117 neutrino.config
118 .plugin(options.extractId)
119 .use(ExtractTextPlugin, [options.extract.plugin]);
120 }
121 });
122
123};