/
UniversalDocumentPlugin.js
67 lines (55 loc) 路 2.27 KB
/
UniversalDocumentPlugin.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
const path = require('path');
const babel = require('@babel/core');
const { RawSource } = require('webpack-sources');
const { readFileSync, existsSync } = require('fs');
const { getBabelConfig } = require('rax-compile-config');
const { createElement } = require('rax');
const { renderToString } = require('rax-server-renderer');
const babelConfig = getBabelConfig();
module.exports = class UniversalDocumentPlugin {
constructor(options) {
if (!options.path) {
throw new Error('Please specify document file location with the path attribute');
}
// for internal weex publish
if (options.publicPath) {
this.publicPath = options.publicPath;
}
// for internal weex publish
if (options.insertScript) {
this.insertScript = options.insertScript;
}
this.documentPath = options.path;
}
apply(compiler) {
compiler.hooks.emit.tapAsync('UniversalDocumentPlugin', (compilation, callback) => {
const config = compilation.options;
const publicPath = this.publicPath ? this.publicPath : config.output.publicPath;
const filename = path.resolve(config.context, this.documentPath);
if (!existsSync(filename)) throw new Error(`File ${filename} is not exists, please check.`);
// get document code
let fileContent = readFileSync(filename, 'utf-8');
if (this.insertScript) {
const insertStr = `\n<script dangerouslySetInnerHTML={{__html: "${this.insertScript}"}} />`;
fileContent = fileContent.replace(/<body>{1}/, '<body>' + insertStr);
}
const { code } = babel.transformSync(fileContent, babelConfig);
// code export
const fn = new Function('module', 'exports', 'require', code);
fn({ exports: {} }, module.exports, require);
const documentElement = module.exports.__esModule ? module.exports.default : module.exports;
const entryObj = config.entry;
Object.keys(entryObj).forEach(entry => {
// get document html string
const pageSource = '<!DOCTYPE html>' + renderToString(createElement(documentElement, {
publicPath,
styles: [],
scripts: [`web/${entry}.js`]
}));
// insert html file
compilation.assets[`web/${entry}.html`] = new RawSource(pageSource);
});
callback();
});
}
};