1 | 'use strict';
|
2 |
|
3 | const invariant = require('invariant');
|
4 | const path = require('path');
|
5 | const webpack = require('webpack');
|
6 |
|
7 | const NodeWatchFileSystem = require('webpack/lib/node/NodeWatchFileSystem');
|
8 | const MultiEntryPlugin = require('webpack/lib/MultiEntryPlugin');
|
9 |
|
10 | const jsxstyleKey = require('./utils/getKey')();
|
11 | const resultLoader = require.resolve('./result-loader');
|
12 |
|
13 | const handledMethods = {
|
14 |
|
15 |
|
16 | mkdir: true,
|
17 | mkdirSync: true,
|
18 | mkdirp: true,
|
19 | mkdirpSync: true,
|
20 | readdir: true,
|
21 | readdirSync: true,
|
22 | readFile: true,
|
23 | readFileSync: true,
|
24 |
|
25 |
|
26 | rmdir: true,
|
27 | rmdirSync: true,
|
28 | stat: true,
|
29 | statSync: true,
|
30 | unlink: true,
|
31 | unlinkSync: true,
|
32 | writeFile: true,
|
33 | writeFileSync: true,
|
34 | };
|
35 |
|
36 | class JsxstyleWebpackPlugin {
|
37 | constructor(options) {
|
38 | options = Object.assign(
|
39 | {
|
40 |
|
41 |
|
42 | __experimental__combineCSS: false,
|
43 |
|
44 |
|
45 | __experimental__extremelyLiteMode: false,
|
46 | },
|
47 | options
|
48 | );
|
49 |
|
50 | this.memoryFS = new webpack.MemoryOutputFileSystem();
|
51 | this.cacheObject = {};
|
52 |
|
53 |
|
54 |
|
55 | this.ctx = {
|
56 | cacheObject: this.cacheObject,
|
57 | memoryFS: this.memoryFS,
|
58 | fileList: new Set(),
|
59 | compileCallback: null,
|
60 | combineCSS: options.__experimental__combineCSS,
|
61 | extremelyLiteMode: options.__experimental__extremelyLiteMode,
|
62 | };
|
63 | }
|
64 |
|
65 | apply(compiler) {
|
66 | const memoryFS = this.memoryFS;
|
67 |
|
68 | if (this.ctx.combineCSS) {
|
69 |
|
70 | compiler.plugin('entry-option', (context, entry) => {
|
71 | const getEntry = (item, name) => {
|
72 | const aggregateFile = path.join(context, name + '.jsxstyle.css');
|
73 | memoryFS.mkdirpSync(context);
|
74 | memoryFS.writeFileSync(aggregateFile, '/* placeholder */');
|
75 |
|
76 | return new MultiEntryPlugin(
|
77 | context,
|
78 | [resultLoader + '!' + aggregateFile].concat(item),
|
79 | name
|
80 | );
|
81 | };
|
82 |
|
83 | if (typeof entry === 'string' || Array.isArray(entry)) {
|
84 | compiler.apply(getEntry(entry, 'main'));
|
85 | } else if (typeof entry === 'object') {
|
86 | Object.keys(entry).forEach(name => {
|
87 | compiler.apply(getEntry(entry[name], name));
|
88 | });
|
89 | }
|
90 |
|
91 | return true;
|
92 | });
|
93 | }
|
94 |
|
95 | compiler.plugin('environment', () => {
|
96 | compiler.inputFileSystem = new Proxy(compiler.inputFileSystem, {
|
97 | get: (target, key) => {
|
98 | const value = target[key];
|
99 |
|
100 | if (handledMethods.hasOwnProperty(key)) {
|
101 | return function(filePath, ...args) {
|
102 | if (filePath.endsWith('.jsxstyle.css')) {
|
103 | process.stderr.write(key + ' -- ' + filePath);
|
104 | return memoryFS[key](filePath, ...args);
|
105 | }
|
106 | return value.call(this, filePath, ...args);
|
107 | };
|
108 | }
|
109 |
|
110 | return value;
|
111 | },
|
112 | });
|
113 |
|
114 | compiler.watchFileSystem = new NodeWatchFileSystem(
|
115 | compiler.inputFileSystem
|
116 | );
|
117 | });
|
118 |
|
119 | compiler.plugin('compilation', compilation => {
|
120 | compilation.plugin('normal-module-loader', loaderContext => {
|
121 | loaderContext[jsxstyleKey] = this.ctx;
|
122 | });
|
123 |
|
124 | if (!this.ctx.combineCSS || compilation.compiler.isChild()) return;
|
125 | });
|
126 | }
|
127 | }
|
128 |
|
129 | module.exports = JsxstyleWebpackPlugin;
|