@qse/edu-scripts 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +333 -0
- package/README.md +105 -0
- package/app.d.ts +68 -0
- package/docs/changelog.md +5 -0
- package/docs/deploy.md +53 -0
- package/docs/feat.md +74 -0
- package/docs/grayscale.md +31 -0
- package/docs/index.md +5 -0
- package/docs/mode.md +42 -0
- package/docs/override.md +165 -0
- package/docs/refactor-react-16.md +40 -0
- package/docs/refactor.md +139 -0
- package/jest.config.js +195 -0
- package/lib/asset/dll/libcommon3-manifest.json +181 -0
- package/lib/asset/template/edu-app-env.d.ts.tpl +15 -0
- package/lib/asset/template/edu-scripts.override.js.tpl +14 -0
- package/lib/asset/template/page/index.class.js.tpl +24 -0
- package/lib/asset/template/page/index.class.tsx.tpl +10 -0
- package/lib/asset/template/page/index.fc.js.tpl +16 -0
- package/lib/asset/template/page/index.fc.tsx.tpl +9 -0
- package/lib/asset/template/page/index.less.tpl +3 -0
- package/lib/asset/template/page/logic.js.tpl +4 -0
- package/lib/asset/template/page/route.js.tpl +12 -0
- package/lib/asset/template/tailwind.config.js.tpl +11 -0
- package/lib/asset/template/tsconfig.json.tpl +24 -0
- package/lib/auto-refactor.js +175 -0
- package/lib/build.js +87 -0
- package/lib/cli.js +63 -0
- package/lib/commit-dist.js +117 -0
- package/lib/config/babel.dependencies.js +56 -0
- package/lib/config/babel.js +82 -0
- package/lib/config/paths.js +44 -0
- package/lib/config/plugins/postcss-safe-area.js +22 -0
- package/lib/config/webpackConfig.js +384 -0
- package/lib/config/webpackDevServerConfig.js +47 -0
- package/lib/deploy.js +186 -0
- package/lib/generator.js +155 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +13 -0
- package/lib/start.js +51 -0
- package/lib/utils/FileSizeReporter.js +131 -0
- package/lib/utils/appConfig.js +44 -0
- package/lib/utils/beforeStart.js +73 -0
- package/lib/utils/changeDeployVersion.js +125 -0
- package/lib/utils/defineConfig.d.ts +59 -0
- package/lib/utils/defineConfig.js +10 -0
- package/lib/utils/exec.js +13 -0
- package/lib/utils/getConfig.js +30 -0
- package/lib/utils/getOverride.js +33 -0
- package/package.json +102 -0
- package/src/asset/dll/libcommon3-manifest.json +181 -0
- package/src/asset/template/edu-app-env.d.ts.tpl +15 -0
- package/src/asset/template/edu-scripts.override.js.tpl +14 -0
- package/src/asset/template/page/index.class.js.tpl +24 -0
- package/src/asset/template/page/index.class.tsx.tpl +10 -0
- package/src/asset/template/page/index.fc.js.tpl +16 -0
- package/src/asset/template/page/index.fc.tsx.tpl +9 -0
- package/src/asset/template/page/index.less.tpl +3 -0
- package/src/asset/template/page/logic.js.tpl +4 -0
- package/src/asset/template/page/route.js.tpl +12 -0
- package/src/asset/template/tailwind.config.js.tpl +11 -0
- package/src/asset/template/tsconfig.json.tpl +24 -0
- package/src/auto-refactor.js +172 -0
- package/src/build.js +74 -0
- package/src/cli.js +91 -0
- package/src/commit-dist.js +103 -0
- package/src/config/babel.dependencies.js +65 -0
- package/src/config/babel.js +88 -0
- package/src/config/paths.js +37 -0
- package/src/config/plugins/postcss-safe-area.js +21 -0
- package/src/config/webpackConfig.js +410 -0
- package/src/config/webpackDevServerConfig.js +44 -0
- package/src/deploy.js +158 -0
- package/src/generator.js +138 -0
- package/src/index.ts +1 -0
- package/src/start.js +46 -0
- package/src/utils/FileSizeReporter.js +144 -0
- package/src/utils/appConfig.js +35 -0
- package/src/utils/beforeStart.js +66 -0
- package/src/utils/changeDeployVersion.js +115 -0
- package/src/utils/defineConfig.ts +63 -0
- package/src/utils/exec.js +7 -0
- package/src/utils/getConfig.js +26 -0
- package/src/utils/getOverride.js +32 -0
- package/tsconfig.json +31 -0
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
|
|
5
|
+
const webpack = require('webpack');
|
|
6
|
+
|
|
7
|
+
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
|
8
|
+
|
|
9
|
+
const {
|
|
10
|
+
BundleAnalyzerPlugin
|
|
11
|
+
} = require('webpack-bundle-analyzer');
|
|
12
|
+
|
|
13
|
+
const ReactRefreshPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
|
|
14
|
+
|
|
15
|
+
const paths = require('./paths');
|
|
16
|
+
|
|
17
|
+
const TerserPlugin = require('terser-webpack-plugin');
|
|
18
|
+
|
|
19
|
+
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
|
|
20
|
+
|
|
21
|
+
const appPkg = require(paths.package);
|
|
22
|
+
|
|
23
|
+
const appConfig = require('../utils/appConfig');
|
|
24
|
+
|
|
25
|
+
const {
|
|
26
|
+
ESBuildMinifyPlugin
|
|
27
|
+
} = require('esbuild-loader');
|
|
28
|
+
|
|
29
|
+
const jsMainPath = appConfig.grayscale ? `${appPkg.name}/beta/${appPkg.name}` : `${appPkg.name}/${appPkg.name}`;
|
|
30
|
+
const assetPath = appConfig.grayscale ? `${appPkg.name}/beta/${appPkg.version}` : `${appPkg.name}/${appPkg.version}`;
|
|
31
|
+
const cssRegex = /\.css$/;
|
|
32
|
+
const cssModuleRegex = /\.module\.css$/;
|
|
33
|
+
const lessRegex = /\.less$/;
|
|
34
|
+
const lessModuleRegex = /\.module\.less$/;
|
|
35
|
+
const imageInlineSizeLimit = 10 * 1024;
|
|
36
|
+
|
|
37
|
+
const qsbCDN = (() => {
|
|
38
|
+
const contents = paths.indexHTML.map(url => fs.readFileSync(url, 'utf-8'));
|
|
39
|
+
const isUseCommon = contents.some(content => /react16.14.*_common31?.js/.test(content));
|
|
40
|
+
const isUseAxios = contents.some(content => /react16.14.*_axios0.21.1/.test(content));
|
|
41
|
+
const isUseMoment = contents.some(content => content.includes('moment2.29.1.js'));
|
|
42
|
+
const isUseAntd = contents.some(content => content.includes('antd3.26.20.js'));
|
|
43
|
+
const isUse = isUseAntd || isUseCommon || isUseMoment || isUseAxios;
|
|
44
|
+
return {
|
|
45
|
+
isUse,
|
|
46
|
+
isUseAntd,
|
|
47
|
+
isUseCommon,
|
|
48
|
+
isUseMoment,
|
|
49
|
+
isUseAxios
|
|
50
|
+
};
|
|
51
|
+
})();
|
|
52
|
+
/**
|
|
53
|
+
* @param {*} args
|
|
54
|
+
* @param {import('../utils/defineConfig').Config} override
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
module.exports = function getWebpackConfig(args, override) {
|
|
59
|
+
var _override$pure_funcs, _override$pure_funcs2;
|
|
60
|
+
|
|
61
|
+
const isDev = process.env.NODE_ENV === 'development';
|
|
62
|
+
const isProd = process.env.NODE_ENV === 'production'; // common function to get style loaders
|
|
63
|
+
|
|
64
|
+
const getStyleLoaders = (cssOptions, preProcessor) => {
|
|
65
|
+
const loaders = [{
|
|
66
|
+
loader: 'style-loader',
|
|
67
|
+
options: {
|
|
68
|
+
attributes: {
|
|
69
|
+
'data-module': appPkg.name,
|
|
70
|
+
'data-version': appPkg.version
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}, {
|
|
74
|
+
loader: 'css-loader',
|
|
75
|
+
options: cssOptions
|
|
76
|
+
}, {
|
|
77
|
+
// Options for PostCSS as we reference these options twice
|
|
78
|
+
// Adds vendor prefixing based on your specified browser support in
|
|
79
|
+
// package.json
|
|
80
|
+
loader: 'postcss-loader',
|
|
81
|
+
options: {
|
|
82
|
+
postcssOptions: {
|
|
83
|
+
// Necessary for external CSS imports to work
|
|
84
|
+
// https://github.com/facebook/create-react-app/issues/2677
|
|
85
|
+
ident: 'postcss',
|
|
86
|
+
config: false,
|
|
87
|
+
plugins: [isProd && require('cssnano')({
|
|
88
|
+
preset: 'default'
|
|
89
|
+
}), fs.existsSync(paths.tailwind) && 'tailwindcss', 'postcss-flexbugs-fixes', ['postcss-preset-env', {
|
|
90
|
+
autoprefixer: {
|
|
91
|
+
flexbox: 'no-2009'
|
|
92
|
+
} // https://preset-env.cssdb.org/features/#stage-2
|
|
93
|
+
|
|
94
|
+
}], isProd && require('./plugins/postcss-safe-area')(), isProd && ['postcss-momentum-scrolling', ['scroll', 'auto']], 'postcss-normalize', ...override.extraPostCSSPlugins].filter(Boolean)
|
|
95
|
+
},
|
|
96
|
+
sourceMap: isDev
|
|
97
|
+
}
|
|
98
|
+
}];
|
|
99
|
+
|
|
100
|
+
if (preProcessor === 'less-loader') {
|
|
101
|
+
loaders.push({
|
|
102
|
+
loader: 'less-loader',
|
|
103
|
+
options: {
|
|
104
|
+
lessOptions: {
|
|
105
|
+
javascriptEnabled: true,
|
|
106
|
+
modifyVars: fs.existsSync(paths.theme) ? require(paths.theme) : undefined
|
|
107
|
+
},
|
|
108
|
+
sourceMap: true
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return loaders;
|
|
114
|
+
};
|
|
115
|
+
/** @type {webpack.Configuration} */
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
const config = {
|
|
119
|
+
context: process.cwd(),
|
|
120
|
+
mode: process.env.NODE_ENV,
|
|
121
|
+
entry: './src/index',
|
|
122
|
+
target: 'browserslist',
|
|
123
|
+
output: {
|
|
124
|
+
filename: appConfig.single ? `js/${jsMainPath}_${appPkg.version}.[contenthash:6].js` : `js/${jsMainPath}_${appPkg.version}.js`,
|
|
125
|
+
chunkFilename: `js/${assetPath}/[name].[chunkhash:8].js`,
|
|
126
|
+
assetModuleFilename: `images/${assetPath}/[name].[hash:6][ext]`,
|
|
127
|
+
uniqueName: appPkg.name,
|
|
128
|
+
publicPath: ''
|
|
129
|
+
},
|
|
130
|
+
externals: Object.assign({}, qsbCDN.isUseCommon && {
|
|
131
|
+
react: 'React',
|
|
132
|
+
'react-dom': 'ReactDOM',
|
|
133
|
+
'natty-fetch': 'nattyFetch',
|
|
134
|
+
'natty-storage': 'nattyStorage',
|
|
135
|
+
'common-utils': 'CommonUtils'
|
|
136
|
+
}, qsbCDN.isUseAxios && {
|
|
137
|
+
axios: 'axios'
|
|
138
|
+
}, qsbCDN.isUseMoment && {
|
|
139
|
+
moment: 'moment'
|
|
140
|
+
}, qsbCDN.isUseAntd && {
|
|
141
|
+
react: 'React',
|
|
142
|
+
'react-dom': 'ReactDOM',
|
|
143
|
+
moment: 'moment',
|
|
144
|
+
antd: 'antd',
|
|
145
|
+
...(isProd && !appConfig.single ? {
|
|
146
|
+
'@qse/antd': 'qsbAntd',
|
|
147
|
+
'@qse/scheme-render': 'qsbSchemeRender',
|
|
148
|
+
'@qsb/antd': 'qsbAntd',
|
|
149
|
+
'@qsb/scheme-render': 'qsbSchemeRender'
|
|
150
|
+
} : {})
|
|
151
|
+
}, override.externals),
|
|
152
|
+
resolve: {
|
|
153
|
+
alias: {
|
|
154
|
+
'@': paths.src,
|
|
155
|
+
...override.alias
|
|
156
|
+
},
|
|
157
|
+
extensions: ['.web.js', '.web.mjs', '.js', '.mjs', '.jsx', '.ts', '.tsx', '.json', '.wasm']
|
|
158
|
+
},
|
|
159
|
+
stats: isDev ? {
|
|
160
|
+
preset: 'errors-warnings',
|
|
161
|
+
timings: true
|
|
162
|
+
} : undefined,
|
|
163
|
+
devtool: isDev ? 'cheap-module-source-map' : false,
|
|
164
|
+
cache: {
|
|
165
|
+
type: 'filesystem',
|
|
166
|
+
version: require('../../package.json').version,
|
|
167
|
+
buildDependencies: {
|
|
168
|
+
config: [__filename],
|
|
169
|
+
override: [paths.override].filter(f => fs.existsSync(f)),
|
|
170
|
+
tsconfig: [paths.tsconfig, paths.jsconfig].filter(f => fs.existsSync(f))
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
module: {
|
|
174
|
+
parser: {
|
|
175
|
+
javascript: {
|
|
176
|
+
exportsPresence: 'error'
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
rules: [{
|
|
180
|
+
oneOf: [// 两个 babel-loader 是为了处理 pdfjs-dist 与 ofd.js
|
|
181
|
+
{
|
|
182
|
+
test: /\.(j|t)sx?$/,
|
|
183
|
+
loader: 'babel-loader',
|
|
184
|
+
include: paths.src,
|
|
185
|
+
options: require('./babel')()
|
|
186
|
+
}, (override.transformNodeModules || isProd) && {
|
|
187
|
+
test: /\.m?js$/,
|
|
188
|
+
loader: 'babel-loader',
|
|
189
|
+
exclude: /@babel(?:\/|\\{1,2})runtime/,
|
|
190
|
+
options: require('./babel.dependencies')()
|
|
191
|
+
}, {
|
|
192
|
+
test: cssRegex,
|
|
193
|
+
exclude: cssModuleRegex,
|
|
194
|
+
use: getStyleLoaders({
|
|
195
|
+
importLoaders: 1,
|
|
196
|
+
sourceMap: isDev,
|
|
197
|
+
modules: {
|
|
198
|
+
mode: 'global',
|
|
199
|
+
localIdentName: '[local]--[hash:base64:6]'
|
|
200
|
+
}
|
|
201
|
+
}),
|
|
202
|
+
sideEffects: true
|
|
203
|
+
}, {
|
|
204
|
+
test: cssModuleRegex,
|
|
205
|
+
use: getStyleLoaders({
|
|
206
|
+
importLoaders: 1,
|
|
207
|
+
sourceMap: isDev,
|
|
208
|
+
modules: {
|
|
209
|
+
mode: 'local',
|
|
210
|
+
localIdentName: '[local]--[hash:base64:6]'
|
|
211
|
+
}
|
|
212
|
+
})
|
|
213
|
+
}, {
|
|
214
|
+
test: lessRegex,
|
|
215
|
+
exclude: lessModuleRegex,
|
|
216
|
+
use: getStyleLoaders({
|
|
217
|
+
importLoaders: 2,
|
|
218
|
+
sourceMap: isDev,
|
|
219
|
+
modules: {
|
|
220
|
+
mode: 'global',
|
|
221
|
+
localIdentName: '[local]--[hash:base64:6]'
|
|
222
|
+
}
|
|
223
|
+
}, 'less-loader'),
|
|
224
|
+
sideEffects: true
|
|
225
|
+
}, {
|
|
226
|
+
test: lessModuleRegex,
|
|
227
|
+
use: getStyleLoaders({
|
|
228
|
+
importLoaders: 2,
|
|
229
|
+
sourceMap: isDev,
|
|
230
|
+
modules: {
|
|
231
|
+
mode: 'local',
|
|
232
|
+
localIdentName: '[local]--[hash:base64:6]'
|
|
233
|
+
}
|
|
234
|
+
}, 'less-loader')
|
|
235
|
+
}, {
|
|
236
|
+
test: /\.(bmp|png|jpe?g|gif|webp)$/,
|
|
237
|
+
type: 'asset',
|
|
238
|
+
parser: {
|
|
239
|
+
dataUrlCondition: {
|
|
240
|
+
maxSize: imageInlineSizeLimit // 10kb
|
|
241
|
+
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}, {
|
|
245
|
+
test: /\.svg$/,
|
|
246
|
+
type: 'asset',
|
|
247
|
+
parser: {
|
|
248
|
+
dataUrlCondition: {
|
|
249
|
+
maxSize: imageInlineSizeLimit // 10kb
|
|
250
|
+
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
issuer: {
|
|
254
|
+
and: [/\.(css|less)$/]
|
|
255
|
+
}
|
|
256
|
+
}, {
|
|
257
|
+
test: /\.svg$/,
|
|
258
|
+
use: [{
|
|
259
|
+
loader: '@svgr/webpack',
|
|
260
|
+
options: {
|
|
261
|
+
prettier: false,
|
|
262
|
+
svgo: false,
|
|
263
|
+
svgoConfig: {
|
|
264
|
+
plugins: [{
|
|
265
|
+
removeViewBox: false
|
|
266
|
+
}]
|
|
267
|
+
},
|
|
268
|
+
titleProp: true,
|
|
269
|
+
ref: false
|
|
270
|
+
}
|
|
271
|
+
}, {
|
|
272
|
+
loader: 'url-loader',
|
|
273
|
+
options: {
|
|
274
|
+
name: `images/${assetPath}/[name].[hash:6].[ext]`,
|
|
275
|
+
limit: imageInlineSizeLimit
|
|
276
|
+
}
|
|
277
|
+
}],
|
|
278
|
+
issuer: {
|
|
279
|
+
and: [/\.(ts|tsx|js|jsx|md|mdx)$/]
|
|
280
|
+
}
|
|
281
|
+
}, {
|
|
282
|
+
// Exclude `js` files to keep "css" loader working as it injects
|
|
283
|
+
// its runtime that would otherwise be processed through "file" loader.
|
|
284
|
+
// Also exclude `html` and `json` extensions so they get processed
|
|
285
|
+
// by webpacks internal loaders.
|
|
286
|
+
exclude: [/^$/, /\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
|
|
287
|
+
type: 'asset/resource'
|
|
288
|
+
}].filter(Boolean)
|
|
289
|
+
}]
|
|
290
|
+
},
|
|
291
|
+
plugins: [qsbCDN.isUseCommon && new webpack.DllReferencePlugin({
|
|
292
|
+
manifest: require('../asset/dll/libcommon3-manifest.json')
|
|
293
|
+
}), new webpack.IgnorePlugin({
|
|
294
|
+
resourceRegExp: /^\.\/locale$/,
|
|
295
|
+
contextRegExp: /moment$/
|
|
296
|
+
}), new webpack.DefinePlugin({
|
|
297
|
+
'process.env.APP_NAME': JSON.stringify(appPkg.name),
|
|
298
|
+
'process.env.APP_VERSION': JSON.stringify(appPkg.version),
|
|
299
|
+
'process.env.BABEL_ENV': JSON.stringify(process.env.BABEL_ENV),
|
|
300
|
+
'process.env.BROWSERSLIST': JSON.stringify(process.env.BROWSERSLIST),
|
|
301
|
+
'process.env.WDS_SOCKET_HOST': JSON.stringify(process.env.WDS_SOCKET_HOST),
|
|
302
|
+
'process.env.WDS_SOCKET_PORT': JSON.stringify(process.env.WDS_SOCKET_PORT),
|
|
303
|
+
...override.define
|
|
304
|
+
}), new webpack.ProgressPlugin(), isDev && new CaseSensitivePathsPlugin(), isDev && new ReactRefreshPlugin({
|
|
305
|
+
overlay: false
|
|
306
|
+
}), ...(isDev || process.env.OUTPUT_HTML || appConfig.single || appConfig.mainProject ? paths.indexHTML.map(template => new HtmlWebpackPlugin({
|
|
307
|
+
template: template,
|
|
308
|
+
filename: template.split('/').pop(),
|
|
309
|
+
inject: false,
|
|
310
|
+
minify: {
|
|
311
|
+
removeComments: true,
|
|
312
|
+
collapseWhitespace: true,
|
|
313
|
+
removeRedundantAttributes: true,
|
|
314
|
+
useShortDoctype: true,
|
|
315
|
+
removeEmptyAttributes: true,
|
|
316
|
+
removeStyleLinkTypeAttributes: true,
|
|
317
|
+
keepClosingSlash: true,
|
|
318
|
+
minifyJS: true,
|
|
319
|
+
minifyCSS: true,
|
|
320
|
+
minifyURLs: true
|
|
321
|
+
}
|
|
322
|
+
})) : []), process.env.ANALYZE && isProd && new BundleAnalyzerPlugin()].filter(Boolean),
|
|
323
|
+
optimization: {
|
|
324
|
+
minimize: isProd && override.minify !== false,
|
|
325
|
+
minimizer: [override.minify === 'esbuild' && new ESBuildMinifyPlugin({
|
|
326
|
+
pure: (_override$pure_funcs = override.pure_funcs) !== null && _override$pure_funcs !== void 0 ? _override$pure_funcs : ['console.log'],
|
|
327
|
+
drop: ['debugger'],
|
|
328
|
+
keepNames: false,
|
|
329
|
+
legalComments: 'none',
|
|
330
|
+
target: 'es5'
|
|
331
|
+
}), // This is only used in production mode
|
|
332
|
+
override.minify === 'terser' && new TerserPlugin({
|
|
333
|
+
extractComments: false,
|
|
334
|
+
terserOptions: {
|
|
335
|
+
parse: {
|
|
336
|
+
// We want terser to parse ecma 8 code. However, we don't want it
|
|
337
|
+
// to apply any minification steps that turns valid ecma 5 code
|
|
338
|
+
// into invalid ecma 5 code. This is why the 'compress' and 'output'
|
|
339
|
+
// sections only apply transformations that are ecma 5 safe
|
|
340
|
+
// https://github.com/facebook/create-react-app/pull/4234
|
|
341
|
+
ecma: 8
|
|
342
|
+
},
|
|
343
|
+
compress: {
|
|
344
|
+
pure_funcs: (_override$pure_funcs2 = override.pure_funcs) !== null && _override$pure_funcs2 !== void 0 ? _override$pure_funcs2 : ['console.log'],
|
|
345
|
+
drop_debugger: true,
|
|
346
|
+
ecma: 5,
|
|
347
|
+
warnings: false,
|
|
348
|
+
// Disabled because of an issue with Uglify breaking seemingly valid code:
|
|
349
|
+
// https://github.com/facebook/create-react-app/issues/2376
|
|
350
|
+
// Pending further investigation:
|
|
351
|
+
// https://github.com/mishoo/UglifyJS2/issues/2011
|
|
352
|
+
comparisons: false,
|
|
353
|
+
// Disabled because of an issue with Terser breaking valid code:
|
|
354
|
+
// https://github.com/facebook/create-react-app/issues/5250
|
|
355
|
+
// Pending further investigation:
|
|
356
|
+
// https://github.com/terser-js/terser/issues/120
|
|
357
|
+
inline: 2
|
|
358
|
+
},
|
|
359
|
+
mangle: {
|
|
360
|
+
safari10: true
|
|
361
|
+
},
|
|
362
|
+
// Added for profiling in devtools
|
|
363
|
+
keep_classnames: false,
|
|
364
|
+
keep_fnames: false,
|
|
365
|
+
output: {
|
|
366
|
+
ecma: 5,
|
|
367
|
+
comments: false,
|
|
368
|
+
// Turned on because emoji and regex is not minified properly using default
|
|
369
|
+
// https://github.com/facebook/create-react-app/issues/2488
|
|
370
|
+
ascii_only: true
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
})].filter(Boolean),
|
|
374
|
+
splitChunks: {
|
|
375
|
+
minChunks: 2
|
|
376
|
+
}
|
|
377
|
+
},
|
|
378
|
+
performance: {
|
|
379
|
+
maxEntrypointSize: appConfig.single ? 1024 * 1024 : 30 * 1024,
|
|
380
|
+
maxAssetSize: 1024 * 1024
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
return config;
|
|
384
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const WebpackDevServer = require('webpack-dev-server');
|
|
4
|
+
/**
|
|
5
|
+
* @param {*} args
|
|
6
|
+
* @param {import('../utils/defineConfig').Config} override
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
module.exports = function getWebpackDevServerConfig(args, override) {
|
|
11
|
+
const host = process.env.HOST || '0.0.0.0';
|
|
12
|
+
const sockHost = process.env.WDS_SOCKET_HOST;
|
|
13
|
+
const sockPort = process.env.WDS_SOCKET_PORT;
|
|
14
|
+
/** @type {WebpackDevServer.Configuration} */
|
|
15
|
+
|
|
16
|
+
const devServer = {
|
|
17
|
+
hot: true,
|
|
18
|
+
allowedHosts: 'all',
|
|
19
|
+
historyApiFallback: true,
|
|
20
|
+
port: args.port,
|
|
21
|
+
open: args.open,
|
|
22
|
+
host,
|
|
23
|
+
client: {
|
|
24
|
+
webSocketURL: {
|
|
25
|
+
protocol: 'auto:',
|
|
26
|
+
hostname: sockHost,
|
|
27
|
+
port: sockPort
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
headers: {
|
|
31
|
+
'Access-Control-Allow-Origin': '*',
|
|
32
|
+
'Access-Control-Allow-Methods': '*',
|
|
33
|
+
'Access-Control-Allow-Headers': '*'
|
|
34
|
+
},
|
|
35
|
+
proxy: [...override.proxy, {
|
|
36
|
+
context: ['/api'],
|
|
37
|
+
target: 'http://192.168.10.19:3339/qsxxwapdev',
|
|
38
|
+
changeOrigin: true,
|
|
39
|
+
headers: {
|
|
40
|
+
host: 'www.zhidianbao.cn',
|
|
41
|
+
origin: 'http://www.zhidianbao.cn'
|
|
42
|
+
}
|
|
43
|
+
}],
|
|
44
|
+
compress: true
|
|
45
|
+
};
|
|
46
|
+
return devServer;
|
|
47
|
+
};
|
package/lib/deploy.js
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
sshSftp
|
|
5
|
+
} = require('@qse/ssh-sftp');
|
|
6
|
+
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
const paths = require('./config/paths');
|
|
10
|
+
|
|
11
|
+
const pkg = require(paths.package);
|
|
12
|
+
|
|
13
|
+
const chalk = require('chalk');
|
|
14
|
+
|
|
15
|
+
const fs = require('fs-extra');
|
|
16
|
+
|
|
17
|
+
const changeDeployVersion = require('./utils/changeDeployVersion');
|
|
18
|
+
|
|
19
|
+
const ora = require('ora');
|
|
20
|
+
|
|
21
|
+
const appConfig = require('./utils/appConfig');
|
|
22
|
+
|
|
23
|
+
const baseConfig = {
|
|
24
|
+
localPath: 'dist',
|
|
25
|
+
ignore: [],
|
|
26
|
+
cleanRemoteFiles: false,
|
|
27
|
+
securityLock: false,
|
|
28
|
+
keepAlive: true,
|
|
29
|
+
noWarn: true
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
async function normalDeploy(args) {
|
|
33
|
+
const presetConfig = {
|
|
34
|
+
s: {
|
|
35
|
+
context: 'eduwebngv1',
|
|
36
|
+
folder: 'userportal'
|
|
37
|
+
},
|
|
38
|
+
b: {
|
|
39
|
+
context: 'eduwebngv1',
|
|
40
|
+
folder: 'bureaupc'
|
|
41
|
+
},
|
|
42
|
+
d: {
|
|
43
|
+
context: 'eduwebngv1',
|
|
44
|
+
folder: 'documentshelves'
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const resolve = (...pathSegments) => path.resolve(process.cwd(), ...pathSegments);
|
|
49
|
+
/**
|
|
50
|
+
* 生成路径
|
|
51
|
+
* @name remoteFile 远程文件
|
|
52
|
+
* @name tmpFile 本地文件
|
|
53
|
+
* @name tmpDir 本地临时文件夹 `tmpFile`存在的文件夹
|
|
54
|
+
* @name tmpBase 本地临时文件夹 到`__tmp__`层
|
|
55
|
+
* @param {string} remoteFilePath 远程文件相对`opts.remotePath`地址
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
function getLocalAndRemoteFilePath(remoteFilePath, opts) {
|
|
60
|
+
const splited = remoteFilePath.split('/');
|
|
61
|
+
const fileName = splited[splited.length - 1];
|
|
62
|
+
const tmpBase = resolve(opts.localPath, '__tmp__');
|
|
63
|
+
const tmpDir = resolve(opts.localPath, '__tmp__', ...splited.slice(0, -1));
|
|
64
|
+
const tmpFile = resolve(tmpDir, fileName);
|
|
65
|
+
const remoteFile = [opts.remotePath, remoteFilePath].join('/');
|
|
66
|
+
return {
|
|
67
|
+
tmpDir,
|
|
68
|
+
tmpFile,
|
|
69
|
+
remoteFile,
|
|
70
|
+
tmpBase
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function upload(opts) {
|
|
75
|
+
// 上传dist文件
|
|
76
|
+
const {
|
|
77
|
+
sftp,
|
|
78
|
+
opts: fullOpts
|
|
79
|
+
} = await sshSftp(opts);
|
|
80
|
+
const spinner = ora('自动更新 ver.js 版本配置').start(); // 指定远程需要修改的文件
|
|
81
|
+
|
|
82
|
+
const fileName = 'js/ver.js'; // 生成各种路径
|
|
83
|
+
|
|
84
|
+
const {
|
|
85
|
+
remoteFile,
|
|
86
|
+
tmpDir,
|
|
87
|
+
tmpFile,
|
|
88
|
+
tmpBase
|
|
89
|
+
} = getLocalAndRemoteFilePath(fileName, fullOpts);
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
// 创建本地临时文件夹,位置在 `opts.localPath` 下的 `__tmp__` 文件夹
|
|
93
|
+
fs.mkdirSync(tmpDir, {
|
|
94
|
+
recursive: true
|
|
95
|
+
}); // 拉取远程文件到本地
|
|
96
|
+
|
|
97
|
+
await sftp.fastGet(remoteFile, tmpFile); // 读取本地文件内容
|
|
98
|
+
|
|
99
|
+
let code = await fs.readFile(tmpFile, {
|
|
100
|
+
encoding: 'utf-8'
|
|
101
|
+
});
|
|
102
|
+
code = changeDeployVersion(code, {
|
|
103
|
+
name: pkg.name,
|
|
104
|
+
version: pkg.version,
|
|
105
|
+
grayscale: appConfig.grayscale
|
|
106
|
+
});
|
|
107
|
+
await sftp.fastPut(tmpFile, remoteFile + '.bak');
|
|
108
|
+
await fs.writeFile(tmpFile, code); // 将修改完的内容传回服务器
|
|
109
|
+
|
|
110
|
+
await sftp.fastPut(tmpFile, remoteFile);
|
|
111
|
+
spinner.succeed('已更新 ver.js 版本配置');
|
|
112
|
+
} catch (e) {
|
|
113
|
+
spinner.fail(`自动修改 ver.js 失败,请手动修改`);
|
|
114
|
+
console.log(chalk.bgRed(e.message));
|
|
115
|
+
} finally {
|
|
116
|
+
await sftp.end(); // 清除临时文件夹
|
|
117
|
+
|
|
118
|
+
fs.removeSync(tmpBase);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const presets = [];
|
|
123
|
+
|
|
124
|
+
if (args.b) {
|
|
125
|
+
presets.push(presetConfig.b);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (args.s) {
|
|
129
|
+
presets.push(presetConfig.s);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (args.d) {
|
|
133
|
+
presets.push(presetConfig.d);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (presets.length === 0) {
|
|
137
|
+
console.log(`
|
|
138
|
+
${chalk.red('指定 deploy 部署范围')}
|
|
139
|
+
|
|
140
|
+
# 部署代码 校端
|
|
141
|
+
${chalk.green('edu-scripts deploy -s')}
|
|
142
|
+
# 部署代码 局端
|
|
143
|
+
${chalk.green('edu-scripts deploy -b')}
|
|
144
|
+
# 部署代码 公文
|
|
145
|
+
${chalk.green('edu-scripts deploy -d')}
|
|
146
|
+
# 部署代码 校端 + 局端
|
|
147
|
+
${chalk.green('edu-scripts deploy -s -b')}
|
|
148
|
+
`);
|
|
149
|
+
process.exit();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const uploadConfig = { ...baseConfig,
|
|
153
|
+
ignore: [...baseConfig.ignore, 'js/ver.js']
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
if (!appConfig.mainProject) {
|
|
157
|
+
uploadConfig.ignore = [...uploadConfig.ignore, '!(js|images)'];
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
for (const preset of presets) {
|
|
161
|
+
await upload({ ...uploadConfig,
|
|
162
|
+
preset
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async function singleDeploy() {
|
|
168
|
+
const config = fs.existsSync(paths.sshSftp) ? fs.readJsonSync(paths.sshSftp) : { ...baseConfig,
|
|
169
|
+
preset: {
|
|
170
|
+
context: 'qsxxwapdev'
|
|
171
|
+
},
|
|
172
|
+
cleanRemoteFiles: true,
|
|
173
|
+
securityLock: true,
|
|
174
|
+
keepAlive: false,
|
|
175
|
+
noWarn: false
|
|
176
|
+
};
|
|
177
|
+
sshSftp(config);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
module.exports = function deploy(args) {
|
|
181
|
+
if (appConfig.single) {
|
|
182
|
+
singleDeploy();
|
|
183
|
+
} else {
|
|
184
|
+
normalDeploy(args);
|
|
185
|
+
}
|
|
186
|
+
};
|