UNPKG

3.84 kBJavaScriptView Raw
1const path = require('path')
2const EventEmitter = require('events')
3const yargs = require('yargs')
4const webpack = require('webpack')
5const PostCompilePlugin = require('post-compile-webpack-plugin')
6const webpackMerge = require('webpack-merge')
7const rm = require('rimraf')
8const ware = require('ware')
9const merge = require('lodash.merge')
10const MemoryFS = require('memory-fs')
11const webpackUtils = require('./webpack-utils')
12const createConfig = require('./create-config')
13const createServer = require('./server')
14const { promisify, readPkg } = require('./utils')
15
16function runWebpack(compiler) {
17 return new Promise((resolve, reject) => {
18 compiler.run((err, stats) => {
19 if (err) return reject(err)
20 resolve(stats)
21 })
22 })
23}
24
25class Poi extends EventEmitter {
26 constructor(options) {
27 super()
28 this.options = Object.assign({
29 cwd: '.',
30 argv: yargs.argv,
31 // Required for cloud IDE like cloud9
32 host: process.env.HOST || '0.0.0.0',
33 port: process.env.PORT || 4000
34 }, options)
35 this.manifest = readPkg()
36 this.webpackConfig = createConfig(this.options)
37 this.webpackConfig.plugin('compile-notifier')
38 .use(PostCompilePlugin, [stats => {
39 if (this.options.mode === 'development' || this.options.mode === 'watch') {
40 this.emit('compile-done', stats)
41 }
42 }])
43 if (this.options.extendWebpack) {
44 this.options.extendWebpack.call(this, this.webpackConfig)
45 }
46 }
47
48 getWebpackConfig() {
49 const config = this.webpackConfig.toConfig()
50 if (this.options.webpack) {
51 return typeof this.options.webpack === 'function' ?
52 this.options.webpack(config) :
53 webpackMerge(config, this.options.webpack)
54 }
55 return config
56 }
57
58 build() {
59 return this.process()
60 .then(() => {
61 this.createCompiler()
62 const { filename, path: outputPath } = this.compiler.options.output
63 // Only remove dist file when name contains hash
64 if (/\[(chunk)?hash:?\d?\]/.test(filename)) {
65 return promisify(rm)(path.join(outputPath, '*'))
66 }
67 })
68 .then(() => runWebpack(this.compiler))
69 }
70
71 watch() {
72 return this.process()
73 .then(() => {
74 this.createCompiler()
75 return this.compiler.watch({}, () => {})
76 })
77 }
78
79 dev() {
80 return this.process()
81 .then(() => {
82 this.createCompiler()
83 return createServer(this.compiler, this.options)
84 })
85 }
86
87 test() {
88 return this.process()
89 }
90
91 createCompiler(webpackConfig = this.getWebpackConfig()) {
92 this.compiler = webpack(webpackConfig)
93 if (this.options.inMemory) {
94 this.compiler.outputFileSystem = new MemoryFS()
95 }
96 return this
97 }
98
99 process(mode = this.options.mode) {
100 const middlewares = []
101
102 const presetContext = {
103 mode: (modes, fn) => {
104 const wildcard = modes === '*'
105 const isMode = typeof modes === 'string' && modes === mode
106 const hasMode = Array.isArray(modes) && modes.indexOf(mode) > -1
107 if (wildcard || isMode || hasMode) {
108 middlewares.push(fn)
109 }
110 },
111 webpackConfig: this.webpackConfig,
112 options: this.options,
113 argv: this.options.argv,
114 manifest: this.manifest,
115 webpackUtils,
116 runWebpack,
117 merge
118 }
119
120 const presets = this.options.presets
121 if (presets) {
122 if (Array.isArray(presets)) {
123 presets.forEach(preset => preset(presetContext))
124 } else {
125 presets(presetContext)
126 }
127 }
128
129 if (!middlewares || middlewares.length === 0) {
130 return Promise.resolve()
131 }
132
133 return new Promise((resolve, reject) => {
134 ware()
135 .use(middlewares)
136 .run(err => {
137 if (err) return reject(err)
138
139 resolve()
140 })
141 })
142 }
143}
144
145module.exports = options => new Poi(options)