UNPKG

5.11 kBJavaScriptView Raw
1'use strict'
2
3// 确保在文件首部设置环境变量
4process.env.BABEL_ENV = 'production'
5process.env.NODE_ENV = 'production'
6
7process.on('unhandledRejection', err => {
8 throw err
9})
10
11const fs = require('fs-extra')
12const path = require('path')
13const chalk = require('chalk')
14const ora = require('ora')
15const glob = require('glob')
16const webpack = require('webpack')
17const { getPageList } = require('../libs/utils')
18const config = require('../config')
19const paths = config.paths
20const maraConf = require(paths.marauder)
21const getWebpackProdConf = require('../webpack/webpack.prod.conf')
22const getWebpackLibConf = require('../webpack/webpack.lib.conf')
23const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages')
24const printBuildError = require('../libs/printBuildError')
25const buildReporter = require('../libs/buildReporter')
26const prehandleConfig = require('../libs/prehandleConfig')
27const Stopwatch = require('../libs/Stopwatch')
28
29const spinner = ora('Build library (commonjs + umd)...')
30
31const pages = getPageList(config.paths.entries)
32const libs = [
33 {
34 format: 'commonjs2',
35 filename: 'index.cjs.js'
36 },
37 {
38 format: 'umd',
39 filename: 'index.min.js',
40 minify: true
41 },
42 {
43 format: 'umd',
44 filename: 'index.js'
45 }
46]
47
48const webpackConfs = libs.concat(pages).map(target => {
49 return typeof target === 'object'
50 ? getWebpackLibConf(target)
51 : getWebpackProdConf({ entry: target, cmd: 'lib' })
52})
53
54function build(dists) {
55 // @TODO 多配置应用 prehandleConfig
56 // const webpackConfig = prehandleConfig('lib', webpackConfig);
57 const ticker = new Stopwatch()
58 const compiler = webpack(webpackConfs)
59
60 return new Promise((resolve, reject) => {
61 ticker.start()
62 compiler.run((err, stats) => {
63 let messages
64 const time = ticker.check()
65
66 spinner.stop()
67
68 if (err) {
69 if (!err.message) {
70 return reject(err)
71 }
72 messages = formatWebpackMessages({
73 errors: [err.message],
74 warnings: []
75 })
76 } else {
77 messages = formatWebpackMessages(
78 stats.toJson({ all: false, warnings: true, errors: true })
79 )
80 }
81
82 if (messages.errors.length) {
83 // Only keep the first error. Others are often indicative
84 // of the same problem, but confuse the reader with noise.
85 if (messages.errors.length > 1) {
86 messages.errors.length = 1
87 }
88 return reject(new Error(messages.errors.join('\n\n')))
89 }
90
91 return resolve({
92 stats,
93 dists,
94 time,
95 warnings: messages.warnings
96 })
97 })
98 })
99}
100
101function clean(dists) {
102 const distArr = Object.values(dists)
103
104 return Promise.all(distArr.map(dir => fs.emptyDir(dir))).then(() => dists)
105}
106
107function success(output) {
108 if (output.warnings.length) {
109 console.log(chalk.yellow('Compiled with warnings:\n'))
110 console.log(output.warnings.join('\n\n'))
111 }
112
113 console.log(chalk.green(`Build complete in ${output.time}ms\n`))
114 console.log('File sizes after gzip:\n')
115
116 const { children } = output.stats.toJson({
117 hash: false,
118 chunks: false,
119 modules: false,
120 chunkModules: false
121 })
122 const compAssets = {
123 lib: children.slice(0, libs.length),
124 demo: children.slice(libs.length)
125 }
126
127 compAssets.lib = compAssets.lib.map((stats, i) => {
128 return stats.assets.map(a => {
129 a['__dist'] = paths.lib
130 a['__format'] = libs[i].format
131 return a
132 })
133 })
134
135 compAssets.demo = compAssets.demo.map((stats, i) => {
136 stats.assets['__dist'] = path.join(paths.dist, pages[i])
137 return stats.assets
138 })
139
140 buildReporter(compAssets)
141}
142
143// 旧版脚手架 umd 文件输出为 dist/main.min.js
144// 通过 --old 配置开启兼容模式
145async function backwards() {
146 if (!process.argv.slice(2).includes('--old')) return
147
148 const umdLibs = glob.sync(path.join(paths.lib, 'index?(.min).js'))
149
150 return Promise.all(
151 umdLibs.map(file => {
152 const name = path.basename(file).replace('index', 'main')
153 return fs.copy(file, path.join(paths.dist, name))
154 })
155 ).then(() => {
156 console.log(
157 chalk.green(
158 '\nSynchronized umd libs to dist for backwards compatibility.'
159 )
160 )
161 })
162}
163
164function error(err) {
165 console.log(chalk.red('Failed to compile.\n'))
166 printBuildError(err)
167 process.exit(1)
168}
169
170function setup(distDir, libDir) {
171 if (!glob.sync(paths.libEntry).length) {
172 console.log(`😶 ${chalk.red('请按如下结构创建入口文件')}`)
173 console.log(
174 `
175 src
176 ├── ${chalk.green('index.(js|ts)')} ${chalk.cyan('-- lib 入口文件')}
177 └── view ${chalk.cyan('-- 视图文件夹,存放 demo 页面')}
178 └── demo ${chalk.cyan('-- demo 页面,可选')}
179 ├── ${chalk.green('index.html')}
180 └── ${chalk.green('index.(js|ts)')}`,
181 '\n'
182 )
183 process.exit(0)
184 }
185
186 spinner.start()
187
188 return clean({
189 distDir,
190 libDir
191 })
192}
193
194module.exports = args => {
195 return setup(paths.dist, paths.lib)
196 .then(build)
197 .then(success)
198 .then(backwards)
199 .catch(error)
200}