1 | 'use strict'
|
2 |
|
3 |
|
4 | process.env.BABEL_ENV = 'production'
|
5 | process.env.NODE_ENV = 'production'
|
6 |
|
7 | process.on('unhandledRejection', err => {
|
8 | throw err
|
9 | })
|
10 |
|
11 | const fs = require('fs-extra')
|
12 | const path = require('path')
|
13 | const chalk = require('chalk')
|
14 | const ora = require('ora')
|
15 | const glob = require('glob')
|
16 | const webpack = require('webpack')
|
17 | const { getPageList } = require('../libs/utils')
|
18 | const config = require('../config')
|
19 | const paths = config.paths
|
20 | const maraConf = require(paths.marauder)
|
21 | const getWebpackProdConf = require('../webpack/webpack.prod.conf')
|
22 | const getWebpackLibConf = require('../webpack/webpack.lib.conf')
|
23 | const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages')
|
24 | const printBuildError = require('../libs/printBuildError')
|
25 | const buildReporter = require('../libs/buildReporter')
|
26 | const prehandleConfig = require('../libs/prehandleConfig')
|
27 | const Stopwatch = require('../libs/Stopwatch')
|
28 |
|
29 | const spinner = ora('Build library (commonjs + umd)...')
|
30 |
|
31 | const pages = getPageList(config.paths.entries)
|
32 | const 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 |
|
48 | const webpackConfs = libs.concat(pages).map(target => {
|
49 | return typeof target === 'object'
|
50 | ? getWebpackLibConf(target)
|
51 | : getWebpackProdConf({ entry: target, cmd: 'lib' })
|
52 | })
|
53 |
|
54 | function build(dists) {
|
55 |
|
56 |
|
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 |
|
84 |
|
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 |
|
101 | function clean(dists) {
|
102 | const distArr = Object.values(dists)
|
103 |
|
104 | return Promise.all(distArr.map(dir => fs.emptyDir(dir))).then(() => dists)
|
105 | }
|
106 |
|
107 | function 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 |
|
144 |
|
145 | async 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 |
|
164 | function error(err) {
|
165 | console.log(chalk.red('Failed to compile.\n'))
|
166 | printBuildError(err)
|
167 | process.exit(1)
|
168 | }
|
169 |
|
170 | function 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 |
|
194 | module.exports = args => {
|
195 | return setup(paths.dist, paths.lib)
|
196 | .then(build)
|
197 | .then(success)
|
198 | .then(backwards)
|
199 | .catch(error)
|
200 | }
|