UNPKG

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