@s-ui/bundler 8.0.0-beta.8 → 9.1.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/README.md +0 -5
- package/bin/sui-bundler-analyzer.js +3 -4
- package/bin/sui-bundler-build.js +1 -1
- package/bin/sui-bundler-dev.js +10 -10
- package/bin/sui-bundler-lib.js +7 -11
- package/factories/createCompiler.js +4 -4
- package/factories/createDevServerConfig.js +21 -14
- package/loaders/linkLoaderConfigBuilder.js +2 -2
- package/package.json +21 -15
- package/shared/minify-js.js +8 -8
- package/utils/WebpackDevServerUtils.js +325 -0
- package/utils/getProcessForPort.js +81 -0
- package/utils/ignoredFiles.js +22 -0
- package/utils/noopServiceWorkerMiddleware.js +40 -0
- package/utils/webpackHotDevClient.js +253 -0
- package/webpack.config.dev.js +23 -13
- package/webpack.config.lib.js +12 -12
- package/webpack.config.prod.js +20 -14
- package/webpack.config.server.js +6 -5
package/README.md
CHANGED
|
@@ -171,7 +171,6 @@ This tool works with zero configuration out the box but you could use some confi
|
|
|
171
171
|
"alias": {
|
|
172
172
|
"react": "preact"
|
|
173
173
|
},
|
|
174
|
-
"measure": true,
|
|
175
174
|
"offline": true,
|
|
176
175
|
"targets": {
|
|
177
176
|
"chrome": "41",
|
|
@@ -213,10 +212,6 @@ You should pass a handler in order to handle when content gets cached for the fi
|
|
|
213
212
|
|
|
214
213
|
If you want to remove your ServiceWorker, you need to use the method `unregister`, the same way you used the `register` method before.
|
|
215
214
|
|
|
216
|
-
### Build time measurement
|
|
217
|
-
|
|
218
|
-
Set `measure` to `true` if you want to check step by step build times.
|
|
219
|
-
|
|
220
215
|
### Only Caching
|
|
221
216
|
|
|
222
217
|
It's possible to create a service worker that caches all static resources
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
/* eslint-disable no-console */
|
|
3
3
|
|
|
4
4
|
const webpack = require('webpack')
|
|
5
|
-
const log = require('../shared/log')
|
|
6
|
-
const config = require('../webpack.config.prod')
|
|
5
|
+
const log = require('../shared/log.js')
|
|
6
|
+
const config = require('../webpack.config.prod.js')
|
|
7
7
|
const {getSpawnPromise} = require('@s-ui/helpers/cli')
|
|
8
8
|
const logUpdate = require('@s-ui/helpers/log-update')
|
|
9
9
|
|
|
@@ -16,10 +16,9 @@ const installNeededDependencies = async () => {
|
|
|
16
16
|
return getSpawnPromise('npm', [
|
|
17
17
|
'install',
|
|
18
18
|
'--no-save',
|
|
19
|
-
'--no-optional',
|
|
20
19
|
'--no-audit',
|
|
21
20
|
'--no-fund',
|
|
22
|
-
'webpack-bundle-analyzer@4.
|
|
21
|
+
'webpack-bundle-analyzer@4.5.0 duplicate-package-checker-webpack-plugin@3.0.0'
|
|
23
22
|
]).then(() => {
|
|
24
23
|
logUpdate.done('Installed needed dependencies')
|
|
25
24
|
getSpawnPromise('./node_modules/.bin/sui-bundler', ['analyzer']).then(
|
package/bin/sui-bundler-build.js
CHANGED
|
@@ -59,7 +59,7 @@ if (clean) {
|
|
|
59
59
|
rimraf.sync(path.resolve(process.env.PWD, 'public'))
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
log.processing('Generating minified bundle
|
|
62
|
+
log.processing('Generating minified bundle...')
|
|
63
63
|
|
|
64
64
|
webpack(nextConfig).run(async (error, stats) => {
|
|
65
65
|
if (error) {
|
package/bin/sui-bundler-dev.js
CHANGED
|
@@ -11,21 +11,18 @@ const WebpackDevServer = require('webpack-dev-server')
|
|
|
11
11
|
|
|
12
12
|
const clearConsole = require('../utils/clearConsole')
|
|
13
13
|
const checkRequiredFiles = require('../utils/checkRequiredFiles')
|
|
14
|
-
const {
|
|
15
|
-
choosePort,
|
|
16
|
-
prepareUrls
|
|
17
|
-
} = require('react-dev-utils/WebpackDevServerUtils')
|
|
14
|
+
const {choosePort, prepareUrls} = require('../utils/WebpackDevServerUtils.js')
|
|
18
15
|
|
|
19
16
|
const webpackConfig = require('../webpack.config.dev')
|
|
20
17
|
|
|
21
18
|
const createDevServerConfig = require('../factories/createDevServerConfig')
|
|
22
19
|
const createCompiler = require('../factories/createCompiler')
|
|
23
20
|
|
|
24
|
-
const linkLoaderConfigBuilder = require('../loaders/linkLoaderConfigBuilder')
|
|
25
|
-
const log = require('../shared/log')
|
|
21
|
+
const linkLoaderConfigBuilder = require('../loaders/linkLoaderConfigBuilder.js')
|
|
22
|
+
const log = require('../shared/log.js')
|
|
26
23
|
|
|
27
|
-
const
|
|
28
|
-
const
|
|
24
|
+
const {CI = false, HOST = '0.0.0.0', HTTPS, PORT} = process.env
|
|
25
|
+
const DEFAULT_PORT = +PORT || 3000
|
|
29
26
|
const DEFAULT_WATCH = !CI
|
|
30
27
|
|
|
31
28
|
if (!module.parent) {
|
|
@@ -81,14 +78,16 @@ const start = async ({
|
|
|
81
78
|
)
|
|
82
79
|
process.exit(1)
|
|
83
80
|
}
|
|
84
|
-
|
|
85
|
-
const
|
|
81
|
+
|
|
82
|
+
const protocol = HTTPS === 'true' ? 'https' : 'http'
|
|
83
|
+
const port = await choosePort(DEFAULT_PORT)
|
|
86
84
|
const urls = prepareUrls(protocol, HOST, port)
|
|
87
85
|
const nextConfig = linkLoaderConfigBuilder({
|
|
88
86
|
config,
|
|
89
87
|
linkAll: program.opts().linkAll,
|
|
90
88
|
packagesToLink
|
|
91
89
|
})
|
|
90
|
+
|
|
92
91
|
const compiler = createCompiler(nextConfig, urls)
|
|
93
92
|
const serverConfig = createDevServerConfig(nextConfig, urls.lanUrlForConfig)
|
|
94
93
|
const devServer = new WebpackDevServer(
|
|
@@ -99,6 +98,7 @@ const start = async ({
|
|
|
99
98
|
},
|
|
100
99
|
compiler
|
|
101
100
|
)
|
|
101
|
+
|
|
102
102
|
log.processing('❯ Starting the development server...\n')
|
|
103
103
|
devServer.startCallback(err => {
|
|
104
104
|
if (err) return log.error(err)
|
package/bin/sui-bundler-lib.js
CHANGED
|
@@ -7,8 +7,8 @@ const webpack = require('webpack')
|
|
|
7
7
|
const path = require('path')
|
|
8
8
|
const {showError, showWarning} = require('@s-ui/helpers/cli')
|
|
9
9
|
const {getPackageJson} = require('@s-ui/helpers/packages')
|
|
10
|
-
const config = require('../webpack.config.lib')
|
|
11
|
-
const log = require('../shared/log')
|
|
10
|
+
const config = require('../webpack.config.lib.js')
|
|
11
|
+
const log = require('../shared/log.js')
|
|
12
12
|
|
|
13
13
|
program
|
|
14
14
|
.usage('[options] <entry>')
|
|
@@ -28,14 +28,10 @@ program
|
|
|
28
28
|
)
|
|
29
29
|
.parse(process.argv)
|
|
30
30
|
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
path: publicPath,
|
|
36
|
-
args: [entry],
|
|
37
|
-
root = false
|
|
38
|
-
} = program.opts()
|
|
31
|
+
const [entry] = program.args
|
|
32
|
+
const options = program.opts()
|
|
33
|
+
const {clean = false, output, umd = false, root = false} = options
|
|
34
|
+
const publicPath = options.path
|
|
39
35
|
|
|
40
36
|
if (!output) {
|
|
41
37
|
showError(new Error('--output is mandatory.'), program)
|
|
@@ -72,7 +68,7 @@ if (clean) {
|
|
|
72
68
|
rimraf.sync(outputFolder)
|
|
73
69
|
}
|
|
74
70
|
|
|
75
|
-
log.processing('Generating minified bundle
|
|
71
|
+
log.processing('Generating minified bundle...')
|
|
76
72
|
|
|
77
73
|
webpack(webpackConfig).run((error, stats) => {
|
|
78
74
|
if (error) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const webpack = require('webpack')
|
|
2
|
-
const formatWebpackMessages = require('../utils/formatWebpackMessages')
|
|
3
|
-
const clearConsole = require('../utils/clearConsole')
|
|
4
|
-
const log = require('../shared/log')
|
|
2
|
+
const formatWebpackMessages = require('../utils/formatWebpackMessages.js')
|
|
3
|
+
const clearConsole = require('../utils/clearConsole.js')
|
|
4
|
+
const log = require('../shared/log.js')
|
|
5
5
|
|
|
6
6
|
const isInteractive = process.stdout.isTTY
|
|
7
7
|
|
|
@@ -14,7 +14,7 @@ const printInstructions = ({urls}) =>
|
|
|
14
14
|
module.exports = (config, urls) => {
|
|
15
15
|
let compiler
|
|
16
16
|
try {
|
|
17
|
-
compiler = webpack(config)
|
|
17
|
+
compiler = webpack(config, () => {})
|
|
18
18
|
} catch (err) {
|
|
19
19
|
log.error(`✖ Failed to compile:\n ${err.message || err}`)
|
|
20
20
|
process.exit(1)
|
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
|
-
const noopServiceWorkerMiddleware = require('
|
|
4
|
-
const ignoredFiles = require('
|
|
3
|
+
const noopServiceWorkerMiddleware = require('../utils/noopServiceWorkerMiddleware.js')
|
|
4
|
+
const ignoredFiles = require('../utils/ignoredFiles.js')
|
|
5
5
|
|
|
6
6
|
const {HOST, HTTPS} = process.env
|
|
7
7
|
const protocol = HTTPS === 'true' ? 'https' : 'http'
|
|
8
8
|
const host = HOST || '0.0.0.0'
|
|
9
9
|
|
|
10
10
|
const getWatchOptions = ({context, watch}) => {
|
|
11
|
-
return
|
|
12
|
-
|
|
13
|
-
ignored: ignoredFiles(context)
|
|
14
|
-
}
|
|
15
|
-
: false
|
|
11
|
+
if (!watch) return false
|
|
12
|
+
return {ignored: ignoredFiles(context)}
|
|
16
13
|
}
|
|
17
14
|
|
|
15
|
+
/** @returns {import('webpack-dev-server').Configuration} */
|
|
18
16
|
module.exports = config => ({
|
|
19
17
|
allowedHosts: 'all',
|
|
20
18
|
client: {
|
|
@@ -23,21 +21,30 @@ module.exports = config => ({
|
|
|
23
21
|
errors: true,
|
|
24
22
|
warnings: false
|
|
25
23
|
},
|
|
26
|
-
progress:
|
|
24
|
+
progress: false
|
|
25
|
+
},
|
|
26
|
+
// Enable gzip compression of generated files
|
|
27
|
+
compress: true,
|
|
28
|
+
headers: {
|
|
29
|
+
'Access-Control-Allow-Origin': '*',
|
|
30
|
+
'Access-Control-Allow-Methods': '*',
|
|
31
|
+
'Access-Control-Allow-Headers': '*'
|
|
27
32
|
},
|
|
28
33
|
static: {
|
|
29
34
|
directory: 'public',
|
|
30
35
|
watch: getWatchOptions(config)
|
|
31
36
|
},
|
|
32
37
|
hot: true,
|
|
33
|
-
https: protocol === 'https',
|
|
34
38
|
host,
|
|
35
39
|
historyApiFallback: {
|
|
36
40
|
disableDotRule: true
|
|
37
41
|
},
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
setupMiddlewares(middlewares, devServer) {
|
|
43
|
+
if (!devServer) throw new Error('webpack-dev-server is not defined')
|
|
44
|
+
|
|
45
|
+
middlewares.push(noopServiceWorkerMiddleware(config.output.publicPath))
|
|
46
|
+
|
|
47
|
+
return middlewares
|
|
48
|
+
},
|
|
49
|
+
server: protocol
|
|
43
50
|
})
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const fg = require('fast-glob')
|
|
2
2
|
const path = require('path')
|
|
3
3
|
|
|
4
|
-
const log = require('../shared/log')
|
|
5
|
-
const {defaultAlias} = require('../shared/resolve-alias')
|
|
4
|
+
const log = require('../shared/log.js')
|
|
5
|
+
const {defaultAlias} = require('../shared/resolve-alias.js')
|
|
6
6
|
const createSassLinkImporter = require('./sassLinkImporter.js')
|
|
7
7
|
|
|
8
8
|
const diccFromAbsolutePaths = (paths, init = {}) =>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@s-ui/bundler",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.1.0",
|
|
4
4
|
"description": "Config-free bundler for ES6 React apps.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"sui-bundler": "./bin/sui-bundler.js"
|
|
@@ -21,30 +21,36 @@
|
|
|
21
21
|
},
|
|
22
22
|
"homepage": "https://github.com/SUI-Components/sui/tree/master/packages/sui-bundler#readme",
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@babel/core": "7.16.
|
|
24
|
+
"@babel/core": "7.16.7",
|
|
25
25
|
"@s-ui/helpers": "1",
|
|
26
26
|
"@s-ui/sass-loader": "1",
|
|
27
|
-
"
|
|
27
|
+
"address": "1.1.2",
|
|
28
|
+
"autoprefixer": "10.4.2",
|
|
28
29
|
"babel-loader": "8.2.3",
|
|
29
30
|
"babel-preset-sui": "3",
|
|
31
|
+
"buffer": "6.0.3",
|
|
30
32
|
"commander": "8.3.0",
|
|
31
33
|
"css-loader": "6.5.1",
|
|
32
|
-
"css-minimizer-webpack-plugin": "3.1
|
|
33
|
-
"esbuild
|
|
34
|
-
"
|
|
34
|
+
"css-minimizer-webpack-plugin": "3.4.1",
|
|
35
|
+
"esbuild": "0.14.14",
|
|
36
|
+
"escape-string-regexp": "4.0.0",
|
|
37
|
+
"fast-glob": "3.2.11",
|
|
38
|
+
"find-free-ports": "3.0.0",
|
|
35
39
|
"html-webpack-plugin": "5.5.0",
|
|
36
|
-
"
|
|
40
|
+
"https-browserify": "1.0.0",
|
|
41
|
+
"mini-css-extract-plugin": "2.5.3",
|
|
42
|
+
"postcss": "8.4.5",
|
|
43
|
+
"postcss-loader": "6.2.1",
|
|
37
44
|
"process": "0.11.10",
|
|
38
|
-
"postcss": "8.3.11",
|
|
39
|
-
"postcss-loader": "6.2.0",
|
|
40
|
-
"react-dev-utils": "11.0.4",
|
|
41
45
|
"rimraf": "3.0.2",
|
|
42
|
-
"sass": "1.
|
|
43
|
-
"
|
|
46
|
+
"sass": "1.49.0",
|
|
47
|
+
"stream-http": "3.2.0",
|
|
48
|
+
"strip-ansi": "6.0.1",
|
|
44
49
|
"style-loader": "3.3.1",
|
|
45
|
-
"
|
|
46
|
-
"webpack
|
|
47
|
-
"webpack-
|
|
50
|
+
"url": "0.11.0",
|
|
51
|
+
"webpack": "5.67.0",
|
|
52
|
+
"webpack-dev-server": "4.7.3",
|
|
53
|
+
"webpack-manifest-plugin": "4.1.1",
|
|
48
54
|
"webpack-node-externals": "3.0.0"
|
|
49
55
|
}
|
|
50
56
|
}
|
package/shared/minify-js.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
3
|
-
const esbuild = ({sourceMap}) =>
|
|
4
|
-
new ESBuildMinifyPlugin({
|
|
5
|
-
target: 'es6',
|
|
6
|
-
sourcemap: sourceMap !== 'none' && sourceMap !== false
|
|
7
|
-
})
|
|
1
|
+
const TerserPlugin = require('terser-webpack-plugin')
|
|
8
2
|
|
|
9
3
|
module.exports = ({extractComments, sourceMap}) =>
|
|
10
|
-
|
|
4
|
+
new TerserPlugin({
|
|
5
|
+
minify: TerserPlugin.esbuildMinify,
|
|
6
|
+
terserOptions: {
|
|
7
|
+
target: 'es6',
|
|
8
|
+
sourcemap: sourceMap !== 'none' && sourceMap !== false
|
|
9
|
+
}
|
|
10
|
+
})
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Copyright (c) 2015-present, Facebook, Inc.
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the MIT license found in the
|
|
7
|
+
* LICENSE file in the root directory of this source tree.
|
|
8
|
+
*/
|
|
9
|
+
'use strict'
|
|
10
|
+
|
|
11
|
+
const address = require('address')
|
|
12
|
+
const fs = require('fs')
|
|
13
|
+
const path = require('path')
|
|
14
|
+
const url = require('url')
|
|
15
|
+
|
|
16
|
+
const {findFreePorts, isFreePort} = require('find-free-ports')
|
|
17
|
+
|
|
18
|
+
const clearConsole = require('./clearConsole.js')
|
|
19
|
+
const formatWebpackMessages = require('./formatWebpackMessages.js')
|
|
20
|
+
const getProcessForPort = require('./getProcessForPort.js')
|
|
21
|
+
|
|
22
|
+
const {bold, cyan, green, yellow, red} = require('@s-ui/helpers/colors')
|
|
23
|
+
|
|
24
|
+
const isInteractive = process.stdout.isTTY
|
|
25
|
+
|
|
26
|
+
function prepareUrls(protocol, host, port, pathname = '/') {
|
|
27
|
+
const formatUrl = hostname =>
|
|
28
|
+
url.format({
|
|
29
|
+
protocol,
|
|
30
|
+
hostname,
|
|
31
|
+
port,
|
|
32
|
+
pathname
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const prettyPrintUrl = hostname =>
|
|
36
|
+
url.format({
|
|
37
|
+
protocol,
|
|
38
|
+
hostname,
|
|
39
|
+
port: bold(port),
|
|
40
|
+
pathname
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
const isUnspecifiedHost = host === '0.0.0.0' || host === '::'
|
|
44
|
+
let prettyHost, lanUrlForConfig, lanUrlForTerminal
|
|
45
|
+
|
|
46
|
+
if (isUnspecifiedHost) {
|
|
47
|
+
prettyHost = 'localhost'
|
|
48
|
+
try {
|
|
49
|
+
// This can only return an IPv4 address
|
|
50
|
+
lanUrlForConfig = address.ip()
|
|
51
|
+
if (lanUrlForConfig) {
|
|
52
|
+
// Check if the address is a private ip
|
|
53
|
+
// https://en.wikipedia.org/wiki/Private_network#Private_IPv4_address_spaces
|
|
54
|
+
if (
|
|
55
|
+
/^10[.]|^172[.](1[6-9]|2[0-9]|3[0-1])[.]|^192[.]168[.]/.test(
|
|
56
|
+
lanUrlForConfig
|
|
57
|
+
)
|
|
58
|
+
) {
|
|
59
|
+
// Address is private, format it for later use
|
|
60
|
+
lanUrlForTerminal = prettyPrintUrl(lanUrlForConfig)
|
|
61
|
+
} else {
|
|
62
|
+
// Address is not private, so we will discard it
|
|
63
|
+
lanUrlForConfig = undefined
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
} catch (_e) {
|
|
67
|
+
// ignored
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
prettyHost = host
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const localUrlForTerminal = prettyPrintUrl(prettyHost)
|
|
74
|
+
const localUrlForBrowser = formatUrl(prettyHost)
|
|
75
|
+
return {
|
|
76
|
+
lanUrlForConfig,
|
|
77
|
+
lanUrlForTerminal,
|
|
78
|
+
localUrlForTerminal,
|
|
79
|
+
localUrlForBrowser
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function printInstructions(appName, urls, useYarn) {
|
|
84
|
+
console.log()
|
|
85
|
+
console.log(`You can now view ${bold(appName)} in the browser.`)
|
|
86
|
+
console.log()
|
|
87
|
+
|
|
88
|
+
if (urls.lanUrlForTerminal) {
|
|
89
|
+
console.log(` ${bold('Local:')} ${urls.localUrlForTerminal}`)
|
|
90
|
+
console.log(` ${bold('On Your Network:')} ${urls.lanUrlForTerminal}`)
|
|
91
|
+
} else {
|
|
92
|
+
console.log(` ${urls.localUrlForTerminal}`)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
console.log()
|
|
96
|
+
console.log('Note that the development build is not optimized.')
|
|
97
|
+
console.log(
|
|
98
|
+
`To create a production build, use ` +
|
|
99
|
+
`${cyan(`${useYarn ? 'yarn' : 'npm run'} build`)}.`
|
|
100
|
+
)
|
|
101
|
+
console.log()
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function createCompiler({
|
|
105
|
+
appName,
|
|
106
|
+
config,
|
|
107
|
+
urls,
|
|
108
|
+
useYarn,
|
|
109
|
+
useTypeScript,
|
|
110
|
+
webpack
|
|
111
|
+
}) {
|
|
112
|
+
// "Compiler" is a low-level interface to webpack.
|
|
113
|
+
// It lets us listen to some events and provide our own custom messages.
|
|
114
|
+
let compiler
|
|
115
|
+
try {
|
|
116
|
+
compiler = webpack(config)
|
|
117
|
+
} catch (err) {
|
|
118
|
+
console.log(red('Failed to compile.'))
|
|
119
|
+
console.log()
|
|
120
|
+
console.log(err.message || err)
|
|
121
|
+
console.log()
|
|
122
|
+
process.exit(1)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// "invalid" event fires when you have changed a file, and webpack is
|
|
126
|
+
// recompiling a bundle. WebpackDevServer takes care to pause serving the
|
|
127
|
+
// bundle, so if you refresh, it'll wait instead of serving the old one.
|
|
128
|
+
// "invalid" is short for "bundle invalidated", it doesn't imply any errors.
|
|
129
|
+
compiler.hooks.invalid.tap('invalid', () => {
|
|
130
|
+
if (isInteractive) {
|
|
131
|
+
clearConsole()
|
|
132
|
+
}
|
|
133
|
+
console.log('Compiling...')
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
let isFirstCompile = true
|
|
137
|
+
|
|
138
|
+
// "done" event fires when webpack has finished recompiling the bundle.
|
|
139
|
+
// Whether or not you have warnings or errors, you will get this event.
|
|
140
|
+
compiler.hooks.done.tap('done', async stats => {
|
|
141
|
+
if (isInteractive) clearConsole()
|
|
142
|
+
|
|
143
|
+
// We have switched off the default webpack output in WebpackDevServer
|
|
144
|
+
// options so we are going to "massage" the warnings and errors and present
|
|
145
|
+
// them in a readable focused way.
|
|
146
|
+
// We only construct the warnings and errors for speed:
|
|
147
|
+
// https://github.com/facebook/create-react-app/issues/4492#issuecomment-421959548
|
|
148
|
+
const statsData = stats.toJson({
|
|
149
|
+
all: false,
|
|
150
|
+
warnings: true,
|
|
151
|
+
errors: true
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
const messages = formatWebpackMessages(statsData)
|
|
155
|
+
const isSuccessful = !messages.errors.length && !messages.warnings.length
|
|
156
|
+
if (isSuccessful) {
|
|
157
|
+
console.log(green('Compiled successfully!'))
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (isSuccessful && (isInteractive || isFirstCompile)) {
|
|
161
|
+
printInstructions(appName, urls, useYarn)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
isFirstCompile = false
|
|
165
|
+
|
|
166
|
+
// If errors exist, only show errors.
|
|
167
|
+
if (messages.errors.length) {
|
|
168
|
+
// Only keep the first error. Others are often indicative
|
|
169
|
+
// of the same problem, but confuse the reader with noise.
|
|
170
|
+
if (messages.errors.length > 1) {
|
|
171
|
+
messages.errors.length = 1
|
|
172
|
+
}
|
|
173
|
+
console.log(red('Failed to compile.\n'))
|
|
174
|
+
console.log(messages.errors.join('\n\n'))
|
|
175
|
+
return
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Show warnings if no errors were found.
|
|
179
|
+
if (messages.warnings.length) {
|
|
180
|
+
console.log(yellow('Compiled with warnings.\n'))
|
|
181
|
+
console.log(messages.warnings.join('\n\n'))
|
|
182
|
+
|
|
183
|
+
// Teach some ESLint tricks.
|
|
184
|
+
console.log(
|
|
185
|
+
`\nSearch for the ${yellow(
|
|
186
|
+
'keywords'
|
|
187
|
+
)} to learn more about each warning.`
|
|
188
|
+
)
|
|
189
|
+
}
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
return compiler
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// We need to provide a custom onError function for httpProxyMiddleware.
|
|
196
|
+
// It allows us to log custom error messages on the console.
|
|
197
|
+
function onProxyError(proxy) {
|
|
198
|
+
return (err, req, res) => {
|
|
199
|
+
const host = req.headers && req.headers.host
|
|
200
|
+
const error = `Proxy error: Could not proxy request ${req.url} from ${host} to ${proxy} (${err.code})`
|
|
201
|
+
console.log(error)
|
|
202
|
+
|
|
203
|
+
console.log(
|
|
204
|
+
'See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (' +
|
|
205
|
+
cyan(err.code) +
|
|
206
|
+
').'
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
// And immediately send the proper error response to the client.
|
|
210
|
+
// Otherwise, the request will eventually timeout with ERR_EMPTY_RESPONSE on the client side.
|
|
211
|
+
if (res.writeHead && !res.headersSent) {
|
|
212
|
+
res.writeHead(500)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
res.end(error)
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function prepareProxy(proxy, appPublicFolder, servedPathname) {
|
|
220
|
+
// `proxy` lets you specify alternate servers for specific requests.
|
|
221
|
+
if (!proxy) return undefined
|
|
222
|
+
|
|
223
|
+
if (typeof proxy !== 'string') {
|
|
224
|
+
console.log(
|
|
225
|
+
red('When specified, "proxy" in package.json must be a string.')
|
|
226
|
+
)
|
|
227
|
+
console.log(red('Instead, the type of "proxy" was "' + typeof proxy + '".'))
|
|
228
|
+
console.log(
|
|
229
|
+
red('Either remove "proxy" from package.json, or make it a string.')
|
|
230
|
+
)
|
|
231
|
+
process.exit(1)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// If proxy is specified, let it handle any request except for
|
|
235
|
+
// files in the public folder and requests to the WebpackDevServer socket endpoint.
|
|
236
|
+
// https://github.com/facebook/create-react-app/issues/6720
|
|
237
|
+
const sockPath = process.env.WDS_SOCKET_PATH || '/ws'
|
|
238
|
+
const isDefaultSockHost = !process.env.WDS_SOCKET_HOST
|
|
239
|
+
function mayProxy(pathname) {
|
|
240
|
+
const maybePublicPath = path.resolve(
|
|
241
|
+
appPublicFolder,
|
|
242
|
+
pathname.replace(new RegExp('^' + servedPathname), '')
|
|
243
|
+
)
|
|
244
|
+
const isPublicFileRequest = fs.existsSync(maybePublicPath)
|
|
245
|
+
// used by webpackHotDevClient
|
|
246
|
+
const isWdsEndpointRequest =
|
|
247
|
+
isDefaultSockHost && pathname.startsWith(sockPath)
|
|
248
|
+
return !(isPublicFileRequest || isWdsEndpointRequest)
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (!/^http(s)?:\/\//.test(proxy)) {
|
|
252
|
+
console.log(
|
|
253
|
+
red(
|
|
254
|
+
'When "proxy" is specified in package.json it must start with either http:// or https://'
|
|
255
|
+
)
|
|
256
|
+
)
|
|
257
|
+
process.exit(1)
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const target = proxy
|
|
261
|
+
|
|
262
|
+
return [
|
|
263
|
+
{
|
|
264
|
+
target,
|
|
265
|
+
logLevel: 'silent',
|
|
266
|
+
// For single page apps, we generally want to fallback to /index.html.
|
|
267
|
+
// However we also want to respect `proxy` for API calls.
|
|
268
|
+
// So if `proxy` is specified as a string, we need to decide which fallback to use.
|
|
269
|
+
// We use a heuristic: We want to proxy all the requests that are not meant
|
|
270
|
+
// for static assets and as all the requests for static assets will be using
|
|
271
|
+
// `GET` method, we can proxy all non-`GET` requests.
|
|
272
|
+
// For `GET` requests, if request `accept`s text/html, we pick /index.html.
|
|
273
|
+
// Modern browsers include text/html into `accept` header when navigating.
|
|
274
|
+
// However API calls like `fetch()` won’t generally accept text/html.
|
|
275
|
+
// If this heuristic doesn’t work well for you, use `src/setupProxy.js`.
|
|
276
|
+
context: function(pathname, req) {
|
|
277
|
+
return (
|
|
278
|
+
req.method !== 'GET' ||
|
|
279
|
+
(mayProxy(pathname) &&
|
|
280
|
+
req.headers.accept &&
|
|
281
|
+
req.headers.accept.indexOf('text/html') === -1)
|
|
282
|
+
)
|
|
283
|
+
},
|
|
284
|
+
onProxyReq: proxyReq => {
|
|
285
|
+
// Browsers may send Origin headers even with same-origin
|
|
286
|
+
// requests. To prevent CORS issues, we have to change
|
|
287
|
+
// the Origin to match the target URL.
|
|
288
|
+
if (proxyReq.getHeader('origin')) {
|
|
289
|
+
proxyReq.setHeader('origin', target)
|
|
290
|
+
}
|
|
291
|
+
},
|
|
292
|
+
onError: onProxyError(target),
|
|
293
|
+
secure: false,
|
|
294
|
+
changeOrigin: true,
|
|
295
|
+
ws: true,
|
|
296
|
+
xfwd: true
|
|
297
|
+
}
|
|
298
|
+
]
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
async function choosePort(defaultPort) {
|
|
302
|
+
const isDefaultPortFree = await isFreePort(defaultPort)
|
|
303
|
+
if (isDefaultPortFree) return defaultPort
|
|
304
|
+
|
|
305
|
+
console.log(`Something is already running on port ${defaultPort}.`)
|
|
306
|
+
|
|
307
|
+
const [freePort] = await findFreePorts(1, {startPort: 3000})
|
|
308
|
+
|
|
309
|
+
if (isInteractive) {
|
|
310
|
+
clearConsole()
|
|
311
|
+
const existingProcess = getProcessForPort(defaultPort)
|
|
312
|
+
if (existingProcess) {
|
|
313
|
+
console.log(`It seems that ${existingProcess} is using the default port.`)
|
|
314
|
+
console.log(green(`Using free port: ${freePort} instead.`))
|
|
315
|
+
}
|
|
316
|
+
return freePort
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
module.exports = {
|
|
321
|
+
choosePort,
|
|
322
|
+
createCompiler,
|
|
323
|
+
prepareProxy,
|
|
324
|
+
prepareUrls
|
|
325
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
'use strict'
|
|
4
|
+
|
|
5
|
+
const {execSync, execFileSync} = require('child_process')
|
|
6
|
+
const {cyan, gray, bold} = require('@s-ui/helpers/colors')
|
|
7
|
+
|
|
8
|
+
/** @type {import('child_process').ExecSyncOptionsWithStringEncoding} */
|
|
9
|
+
const execOptions = {
|
|
10
|
+
encoding: 'utf8',
|
|
11
|
+
stdio: [
|
|
12
|
+
'pipe', // stdin (default)
|
|
13
|
+
'pipe', // stdout (default)
|
|
14
|
+
'ignore' // stderr
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Get the process id for a given port.
|
|
20
|
+
* @param {number} port - The port to look for
|
|
21
|
+
* @returns {string} The process id
|
|
22
|
+
*/
|
|
23
|
+
function getProcessIdOnPort(port) {
|
|
24
|
+
return execFileSync(
|
|
25
|
+
'lsof',
|
|
26
|
+
[`-i:${port}`, '-P', '-t', '-sTCP:LISTEN'],
|
|
27
|
+
execOptions
|
|
28
|
+
)
|
|
29
|
+
.split('\n')[0]
|
|
30
|
+
.trim()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Get the command for a given process id.
|
|
35
|
+
* @param {string} processId - The process id
|
|
36
|
+
* @returns {string} - The process name
|
|
37
|
+
*/
|
|
38
|
+
function getProcessCommand(processId) {
|
|
39
|
+
const command = execSync(
|
|
40
|
+
'ps -o command -p ' + processId + ' | sed -n 2p',
|
|
41
|
+
execOptions
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
return command.replace(/\n$/, '')
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Get the directory of a process by its id.
|
|
49
|
+
* @param {string} processId - The process id
|
|
50
|
+
* @returns {string} - The process directory
|
|
51
|
+
*/
|
|
52
|
+
function getDirectoryOfProcessById(processId) {
|
|
53
|
+
return execSync(
|
|
54
|
+
`lsof -p ${processId} | awk '$4=="cwd" {for (i=9; i<=NF; i++) printf "%s ", $i}'`,
|
|
55
|
+
execOptions
|
|
56
|
+
).trim()
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Get all the information about a process running in a port
|
|
61
|
+
* @param {number} port - The port to look for
|
|
62
|
+
* @returns {null |}
|
|
63
|
+
*/
|
|
64
|
+
function getProcessForPort(port) {
|
|
65
|
+
try {
|
|
66
|
+
const processId = getProcessIdOnPort(port)
|
|
67
|
+
const directory = getDirectoryOfProcessById(processId)
|
|
68
|
+
const command = getProcessCommand(processId)
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
bold(command) +
|
|
72
|
+
gray(' (pid ' + processId + ')\n') +
|
|
73
|
+
gray(' in ') +
|
|
74
|
+
cyan(directory)
|
|
75
|
+
)
|
|
76
|
+
} catch (e) {
|
|
77
|
+
return null
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
module.exports = getProcessForPort
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Extracted from: https://github.com/facebook/create-react-app/blob/bb64e31a81eb12d688c14713dce812143688750a/packages/react-dev-utils/ignoredFiles.js
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Copyright (c) 2015-present, Facebook, Inc.
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the MIT license found in the
|
|
7
|
+
* LICENSE file in the root directory of this source tree.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
'use strict'
|
|
11
|
+
|
|
12
|
+
const path = require('path')
|
|
13
|
+
const escape = require('escape-string-regexp')
|
|
14
|
+
|
|
15
|
+
module.exports = function ignoredFiles(appSrc) {
|
|
16
|
+
return new RegExp(
|
|
17
|
+
`^(?!${escape(
|
|
18
|
+
path.normalize(appSrc + '/').replace(/[\\]+/g, '/')
|
|
19
|
+
)}).+/node_modules/`,
|
|
20
|
+
'g'
|
|
21
|
+
)
|
|
22
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// from: https://github.com/facebook/create-react-app/blob/main/packages/react-dev-utils/noopServiceWorkerMiddleware.js
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Copyright (c) 2015-present, Facebook, Inc.
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the MIT license found in the
|
|
7
|
+
* LICENSE file in the root directory of this source tree.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
'use strict'
|
|
11
|
+
|
|
12
|
+
const path = require('path')
|
|
13
|
+
|
|
14
|
+
module.exports = function createNoopServiceWorkerMiddleware(servedPath) {
|
|
15
|
+
return function noopServiceWorkerMiddleware(req, res, next) {
|
|
16
|
+
if (req.url === path.join(servedPath, 'service-worker.js')) {
|
|
17
|
+
res.setHeader('Content-Type', 'text/javascript')
|
|
18
|
+
res.send(
|
|
19
|
+
`// This service worker file is effectively a 'no-op' that will reset any
|
|
20
|
+
// previous service worker registered for the same host:port combination.
|
|
21
|
+
// In the production build, this file is replaced with an actual service worker
|
|
22
|
+
// file that will precache your site's local assets.
|
|
23
|
+
// See https://github.com/facebook/create-react-app/issues/2272#issuecomment-302832432
|
|
24
|
+
self.addEventListener('install', () => self.skipWaiting());
|
|
25
|
+
self.addEventListener('activate', () => {
|
|
26
|
+
self.clients.matchAll({ type: 'window' }).then(windowClients => {
|
|
27
|
+
for (let windowClient of windowClients) {
|
|
28
|
+
// Force open pages to refresh, so that they have a chance to load the
|
|
29
|
+
// fresh navigation response from the local dev server.
|
|
30
|
+
windowClient.navigate(windowClient.url);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
`
|
|
35
|
+
)
|
|
36
|
+
} else {
|
|
37
|
+
next()
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/* globals __webpack_hash__ */
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Copyright (c) 2015-present, Facebook, Inc.
|
|
7
|
+
*
|
|
8
|
+
* This source code is licensed under the MIT license found in the
|
|
9
|
+
* LICENSE file in the root directory of this source tree.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
'use strict'
|
|
13
|
+
|
|
14
|
+
// This alternative WebpackDevServer combines the functionality of:
|
|
15
|
+
// https://github.com/webpack/webpack-dev-server/blob/webpack-1/client/index.js
|
|
16
|
+
// https://github.com/webpack/webpack/blob/webpack-1/hot/dev-server.js
|
|
17
|
+
|
|
18
|
+
// It only supports their simplest configuration (hot updates on same server).
|
|
19
|
+
// It makes some opinionated choices on top, like adding a syntax error overlay
|
|
20
|
+
// that looks similar to our console output. The error overlay is inspired by:
|
|
21
|
+
// https://github.com/glenjamin/webpack-hot-middleware
|
|
22
|
+
|
|
23
|
+
const stripAnsi = require('strip-ansi')
|
|
24
|
+
const url = require('url')
|
|
25
|
+
const formatWebpackMessages = require('./formatWebpackMessages.js')
|
|
26
|
+
|
|
27
|
+
// We need to keep track of if there has been a runtime error.
|
|
28
|
+
// Essentially, we cannot guarantee application state was not corrupted by the
|
|
29
|
+
// runtime error. To prevent confusing behavior, we forcibly reload the entire
|
|
30
|
+
// application. This is handled below when we are notified of a compile (code
|
|
31
|
+
// change).
|
|
32
|
+
// See https://github.com/facebook/create-react-app/issues/3096
|
|
33
|
+
const hadRuntimeError = false
|
|
34
|
+
|
|
35
|
+
// Connect to WebpackDevServer via a socket.
|
|
36
|
+
const connection = new WebSocket(
|
|
37
|
+
url.format({
|
|
38
|
+
protocol: window.location.protocol === 'https:' ? 'wss' : 'ws',
|
|
39
|
+
hostname: process.env.WDS_SOCKET_HOST || window.location.hostname,
|
|
40
|
+
port: process.env.WDS_SOCKET_PORT || window.location.port,
|
|
41
|
+
// Hardcoded in WebpackDevServer
|
|
42
|
+
pathname: process.env.WDS_SOCKET_PATH || '/ws',
|
|
43
|
+
slashes: true
|
|
44
|
+
})
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
// Unlike WebpackDevServer client, we won't try to reconnect
|
|
48
|
+
// to avoid spamming the console. Disconnect usually happens
|
|
49
|
+
// when developer stops the server.
|
|
50
|
+
connection.onclose = function() {
|
|
51
|
+
if (typeof console !== 'undefined' && typeof console.info === 'function') {
|
|
52
|
+
console.info(
|
|
53
|
+
'The development server has disconnected.\nRefresh the page if necessary.'
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Remember some state related to hot module replacement.
|
|
59
|
+
let isFirstCompilation = true
|
|
60
|
+
let mostRecentCompilationHash = null
|
|
61
|
+
let hasCompileErrors = false
|
|
62
|
+
|
|
63
|
+
function clearOutdatedErrors() {
|
|
64
|
+
// Clean up outdated compile errors, if any.
|
|
65
|
+
if (typeof console !== 'undefined' && typeof console.clear === 'function') {
|
|
66
|
+
if (hasCompileErrors) {
|
|
67
|
+
console.clear()
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Successful compilation.
|
|
73
|
+
function handleSuccess() {
|
|
74
|
+
clearOutdatedErrors()
|
|
75
|
+
|
|
76
|
+
const isHotUpdate = !isFirstCompilation
|
|
77
|
+
isFirstCompilation = false
|
|
78
|
+
hasCompileErrors = false
|
|
79
|
+
|
|
80
|
+
// Attempt to apply hot updates or reload.
|
|
81
|
+
if (isHotUpdate) {
|
|
82
|
+
tryApplyUpdates()
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Compilation with warnings (e.g. ESLint).
|
|
87
|
+
function handleWarnings(warnings) {
|
|
88
|
+
clearOutdatedErrors()
|
|
89
|
+
|
|
90
|
+
const isHotUpdate = !isFirstCompilation
|
|
91
|
+
isFirstCompilation = false
|
|
92
|
+
hasCompileErrors = false
|
|
93
|
+
|
|
94
|
+
function printWarnings() {
|
|
95
|
+
// Print warnings to the console.
|
|
96
|
+
const formatted = formatWebpackMessages({
|
|
97
|
+
warnings: warnings,
|
|
98
|
+
errors: []
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
if (typeof console !== 'undefined' && typeof console.warn === 'function') {
|
|
102
|
+
for (let i = 0; i < formatted.warnings.length; i++) {
|
|
103
|
+
if (i === 5) {
|
|
104
|
+
console.warn(
|
|
105
|
+
'There were more warnings in other files.\n' +
|
|
106
|
+
'You can find a complete log in the terminal.'
|
|
107
|
+
)
|
|
108
|
+
break
|
|
109
|
+
}
|
|
110
|
+
console.warn(stripAnsi(formatted.warnings[i]))
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
printWarnings()
|
|
116
|
+
|
|
117
|
+
// Attempt to apply hot updates or reload.
|
|
118
|
+
if (isHotUpdate) {
|
|
119
|
+
tryApplyUpdates()
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Compilation with errors (e.g. syntax error or missing modules).
|
|
124
|
+
function handleErrors(errors) {
|
|
125
|
+
clearOutdatedErrors()
|
|
126
|
+
|
|
127
|
+
isFirstCompilation = false
|
|
128
|
+
hasCompileErrors = true
|
|
129
|
+
|
|
130
|
+
// "Massage" webpack messages.
|
|
131
|
+
const formatted = formatWebpackMessages({
|
|
132
|
+
errors: errors,
|
|
133
|
+
warnings: []
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
// Also log them to the console.
|
|
137
|
+
if (typeof console !== 'undefined' && typeof console.error === 'function') {
|
|
138
|
+
for (let i = 0; i < formatted.errors.length; i++) {
|
|
139
|
+
console.error(stripAnsi(formatted.errors[i]))
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Do not attempt to reload now.
|
|
144
|
+
// We will reload on next success instead.
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// There is a newer version of the code available.
|
|
148
|
+
function handleAvailableHash(hash) {
|
|
149
|
+
// Update last known compilation hash.
|
|
150
|
+
mostRecentCompilationHash = hash
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Handle messages from the server.
|
|
154
|
+
connection.onmessage = function(e) {
|
|
155
|
+
const message = JSON.parse(e.data)
|
|
156
|
+
switch (message.type) {
|
|
157
|
+
case 'hash':
|
|
158
|
+
handleAvailableHash(message.data)
|
|
159
|
+
break
|
|
160
|
+
case 'still-ok':
|
|
161
|
+
case 'ok':
|
|
162
|
+
handleSuccess()
|
|
163
|
+
break
|
|
164
|
+
case 'content-changed':
|
|
165
|
+
// Triggered when a file from `contentBase` changed.
|
|
166
|
+
window.location.reload()
|
|
167
|
+
break
|
|
168
|
+
case 'warnings':
|
|
169
|
+
handleWarnings(message.data)
|
|
170
|
+
break
|
|
171
|
+
case 'errors':
|
|
172
|
+
handleErrors(message.data)
|
|
173
|
+
break
|
|
174
|
+
default:
|
|
175
|
+
// Do nothing.
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Is there a newer version of this code available?
|
|
180
|
+
function isUpdateAvailable() {
|
|
181
|
+
// __webpack_hash__ is the hash of the current compilation.
|
|
182
|
+
// It's a global variable injected by webpack.
|
|
183
|
+
// eslint-disable-next-line camelcase
|
|
184
|
+
return mostRecentCompilationHash !== __webpack_hash__
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// webpack disallows updates in other states.
|
|
188
|
+
function canApplyUpdates() {
|
|
189
|
+
return module.hot.status() === 'idle'
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function canAcceptErrors() {
|
|
193
|
+
// NOTE: This var is injected by Webpack's DefinePlugin, and is a boolean instead of string.
|
|
194
|
+
const hasReactRefresh = process.env.FAST_REFRESH
|
|
195
|
+
|
|
196
|
+
const status = module.hot.status()
|
|
197
|
+
// React refresh can handle hot-reloading over errors.
|
|
198
|
+
// However, when hot-reload status is abort or fail,
|
|
199
|
+
// it indicates the current update cannot be applied safely,
|
|
200
|
+
// and thus we should bail out to a forced reload for consistency.
|
|
201
|
+
return hasReactRefresh && ['abort', 'fail'].indexOf(status) === -1
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Attempt to update code on the fly, fall back to a hard reload.
|
|
205
|
+
function tryApplyUpdates(onHotUpdateSuccess) {
|
|
206
|
+
if (!module.hot) {
|
|
207
|
+
// HotModuleReplacementPlugin is not in webpack configuration.
|
|
208
|
+
window.location.reload()
|
|
209
|
+
return
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (!isUpdateAvailable() || !canApplyUpdates()) {
|
|
213
|
+
return
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function handleApplyUpdates(err, updatedModules) {
|
|
217
|
+
const haveErrors = err || hadRuntimeError
|
|
218
|
+
// When there is no error but updatedModules is unavailable,
|
|
219
|
+
// it indicates a critical failure in hot-reloading,
|
|
220
|
+
// e.g. server is not ready to serve new bundle,
|
|
221
|
+
// and hence we need to do a forced reload.
|
|
222
|
+
const needsForcedReload = !err && !updatedModules
|
|
223
|
+
if ((haveErrors && !canAcceptErrors()) || needsForcedReload) {
|
|
224
|
+
window.location.reload()
|
|
225
|
+
return
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (typeof onHotUpdateSuccess === 'function') {
|
|
229
|
+
// Maybe we want to do something.
|
|
230
|
+
onHotUpdateSuccess()
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (isUpdateAvailable()) {
|
|
234
|
+
// While we were updating, there was a new update! Do it again.
|
|
235
|
+
tryApplyUpdates()
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// https://webpack.github.io/docs/hot-module-replacement.html#check
|
|
240
|
+
const result = module.hot.check(/* autoApply */ true, handleApplyUpdates)
|
|
241
|
+
|
|
242
|
+
// // webpack 2 returns a Promise instead of invoking a callback
|
|
243
|
+
if (result && result.then) {
|
|
244
|
+
result.then(
|
|
245
|
+
function(updatedModules) {
|
|
246
|
+
handleApplyUpdates(null, updatedModules)
|
|
247
|
+
},
|
|
248
|
+
function(err) {
|
|
249
|
+
handleApplyUpdates(err, null)
|
|
250
|
+
}
|
|
251
|
+
)
|
|
252
|
+
}
|
|
253
|
+
}
|
package/webpack.config.dev.js
CHANGED
|
@@ -3,22 +3,28 @@
|
|
|
3
3
|
const path = require('path')
|
|
4
4
|
const webpack = require('webpack')
|
|
5
5
|
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
|
6
|
-
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin')
|
|
7
6
|
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
const {
|
|
8
|
+
envVars,
|
|
9
|
+
MAIN_ENTRY_POINT,
|
|
10
|
+
config,
|
|
11
|
+
cleanList,
|
|
12
|
+
when
|
|
13
|
+
} = require('./shared/index.js')
|
|
14
|
+
const definePlugin = require('./shared/define.js')
|
|
15
|
+
const manifestLoaderRules = require('./shared/module-rules-manifest-loader.js')
|
|
16
|
+
const {aliasFromConfig, defaultAlias} = require('./shared/resolve-alias.js')
|
|
17
|
+
|
|
18
|
+
const {resolveLoader} = require('./shared/resolve-loader.js')
|
|
13
19
|
|
|
14
20
|
const EXCLUDED_FOLDERS_REGEXP = new RegExp(
|
|
15
21
|
`node_modules(?!${path.sep}@s-ui(${path.sep}studio)(${path.sep}workbench)?${path.sep}src)`
|
|
16
22
|
)
|
|
17
23
|
const outputPath = path.join(process.cwd(), 'dist')
|
|
18
24
|
|
|
19
|
-
process.env
|
|
25
|
+
const {CI = false} = process.env
|
|
20
26
|
|
|
21
|
-
|
|
27
|
+
process.env.NODE_ENV = 'development'
|
|
22
28
|
|
|
23
29
|
/** @typedef {import('webpack').Configuration} WebpackConfig */
|
|
24
30
|
|
|
@@ -32,14 +38,18 @@ const webpackConfig = {
|
|
|
32
38
|
...aliasFromConfig
|
|
33
39
|
},
|
|
34
40
|
fallback: {
|
|
35
|
-
fs: false
|
|
41
|
+
fs: false,
|
|
42
|
+
http: require.resolve('stream-http'),
|
|
43
|
+
https: require.resolve('https-browserify'),
|
|
44
|
+
buffer: require.resolve('buffer/'),
|
|
45
|
+
url: require.resolve('url/')
|
|
36
46
|
},
|
|
37
47
|
modules: ['node_modules', path.resolve(process.cwd())],
|
|
38
48
|
extensions: ['.js', '.json']
|
|
39
49
|
},
|
|
40
50
|
stats: 'errors-only',
|
|
41
51
|
entry: cleanList([
|
|
42
|
-
require.resolve('
|
|
52
|
+
require.resolve('./utils/webpackHotDevClient.js'),
|
|
43
53
|
MAIN_ENTRY_POINT
|
|
44
54
|
]),
|
|
45
55
|
target: 'web',
|
|
@@ -58,7 +68,7 @@ const webpackConfig = {
|
|
|
58
68
|
},
|
|
59
69
|
plugins: [
|
|
60
70
|
new webpack.ProvidePlugin({
|
|
61
|
-
process: 'process/browser'
|
|
71
|
+
process: 'process/browser.js'
|
|
62
72
|
}),
|
|
63
73
|
new webpack.EnvironmentPlugin(envVars(config.env)),
|
|
64
74
|
definePlugin({__DEV__: true}),
|
|
@@ -116,9 +126,9 @@ const webpackConfig = {
|
|
|
116
126
|
)
|
|
117
127
|
])
|
|
118
128
|
},
|
|
119
|
-
watch:
|
|
129
|
+
watch: !CI,
|
|
120
130
|
devtool:
|
|
121
131
|
config.sourcemaps && config.sourcemaps.dev ? config.sourcemaps.dev : false
|
|
122
132
|
}
|
|
123
133
|
|
|
124
|
-
module.exports =
|
|
134
|
+
module.exports = webpackConfig
|
package/webpack.config.lib.js
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
const webpack = require('webpack')
|
|
2
|
-
const {
|
|
2
|
+
const {
|
|
3
|
+
cleanList,
|
|
4
|
+
envVars,
|
|
5
|
+
MAIN_ENTRY_POINT,
|
|
6
|
+
config
|
|
7
|
+
} = require('./shared/index.js')
|
|
3
8
|
const path = require('path')
|
|
4
|
-
const minifyJs = require('./shared/minify-js')
|
|
5
|
-
const definePlugin = require('./shared/define')
|
|
6
|
-
const babelRules = require('./shared/module-rules-babel')
|
|
7
|
-
const {extractComments, sourceMap} = require('./shared/config')
|
|
8
|
-
const {aliasFromConfig} = require('./shared/resolve-alias')
|
|
9
|
+
const minifyJs = require('./shared/minify-js.js')
|
|
10
|
+
const definePlugin = require('./shared/define.js')
|
|
11
|
+
const babelRules = require('./shared/module-rules-babel.js')
|
|
12
|
+
const {extractComments, sourceMap} = require('./shared/config.js')
|
|
13
|
+
const {aliasFromConfig} = require('./shared/resolve-alias.js')
|
|
9
14
|
|
|
10
15
|
module.exports = {
|
|
11
16
|
mode: 'production',
|
|
@@ -24,12 +29,12 @@ module.exports = {
|
|
|
24
29
|
: MAIN_ENTRY_POINT,
|
|
25
30
|
target: 'web',
|
|
26
31
|
output: {
|
|
27
|
-
jsonpFunction: 'suiWebpackJsonp',
|
|
28
32
|
filename: 'index.js'
|
|
29
33
|
},
|
|
30
34
|
optimization: {
|
|
31
35
|
// avoid looping over all the modules after the compilation
|
|
32
36
|
checkWasmTypes: false,
|
|
37
|
+
minimize: true,
|
|
33
38
|
minimizer: [minifyJs({extractComments, sourceMap})]
|
|
34
39
|
},
|
|
35
40
|
plugins: cleanList([
|
|
@@ -41,10 +46,5 @@ module.exports = {
|
|
|
41
46
|
]),
|
|
42
47
|
module: {
|
|
43
48
|
rules: [babelRules]
|
|
44
|
-
},
|
|
45
|
-
node: {
|
|
46
|
-
fs: 'empty',
|
|
47
|
-
net: 'empty',
|
|
48
|
-
tls: 'empty'
|
|
49
49
|
}
|
|
50
50
|
}
|
package/webpack.config.prod.js
CHANGED
|
@@ -8,22 +8,22 @@ const HtmlWebpackPlugin = require('html-webpack-plugin')
|
|
|
8
8
|
const {WebpackManifestPlugin} = require('webpack-manifest-plugin')
|
|
9
9
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
|
10
10
|
const InlineChunkHtmlPlugin = require('./shared/inline-chunk-html-plugin.js')
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
const {
|
|
13
13
|
when,
|
|
14
14
|
cleanList,
|
|
15
15
|
envVars,
|
|
16
16
|
MAIN_ENTRY_POINT,
|
|
17
17
|
config
|
|
18
|
-
} = require('./shared/index')
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
const babelRules = require('./shared/module-rules-babel')
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
const
|
|
18
|
+
} = require('./shared/index.js')
|
|
19
|
+
const {aliasFromConfig} = require('./shared/resolve-alias.js')
|
|
20
|
+
const {extractComments, sourceMap} = require('./shared/config.js')
|
|
21
|
+
const {resolveLoader} = require('./shared/resolve-loader.js')
|
|
22
|
+
const babelRules = require('./shared/module-rules-babel.js')
|
|
23
|
+
const definePlugin = require('./shared/define.js')
|
|
24
|
+
const manifestLoaderRules = require('./shared/module-rules-manifest-loader.js')
|
|
25
|
+
const minifyCss = require('./shared/minify-css.js')
|
|
26
|
+
const minifyJs = require('./shared/minify-js.js')
|
|
27
27
|
|
|
28
28
|
const PUBLIC_PATH = process.env.CDN || config.cdn || '/'
|
|
29
29
|
|
|
@@ -35,8 +35,6 @@ const cssFileName = config.onlyHash
|
|
|
35
35
|
? '[contenthash:8].css'
|
|
36
36
|
: '[name].[contenthash:8].css'
|
|
37
37
|
|
|
38
|
-
const smp = new SpeedMeasurePlugin()
|
|
39
|
-
|
|
40
38
|
/** @typedef {import('webpack').Configuration} WebpackConfig */
|
|
41
39
|
|
|
42
40
|
/** @type {WebpackConfig} */
|
|
@@ -51,6 +49,8 @@ const webpackConfig = {
|
|
|
51
49
|
fallback: {
|
|
52
50
|
assert: false,
|
|
53
51
|
fs: false,
|
|
52
|
+
http: require.resolve('stream-http'),
|
|
53
|
+
https: require.resolve('https-browserify'),
|
|
54
54
|
path: false
|
|
55
55
|
}
|
|
56
56
|
},
|
|
@@ -67,9 +67,15 @@ const webpackConfig = {
|
|
|
67
67
|
minimizer: [minifyJs({extractComments, sourceMap}), minifyCss()].filter(
|
|
68
68
|
Boolean
|
|
69
69
|
),
|
|
70
|
-
runtimeChunk: true
|
|
70
|
+
runtimeChunk: true,
|
|
71
|
+
splitChunks: {
|
|
72
|
+
chunks: 'all'
|
|
73
|
+
}
|
|
71
74
|
},
|
|
72
75
|
plugins: cleanList([
|
|
76
|
+
new webpack.ProvidePlugin({
|
|
77
|
+
process: 'process/browser'
|
|
78
|
+
}),
|
|
73
79
|
new webpack.ids.HashedModuleIdsPlugin(),
|
|
74
80
|
new webpack.EnvironmentPlugin(envVars(config.env)),
|
|
75
81
|
definePlugin(),
|
|
@@ -133,4 +139,4 @@ const webpackConfig = {
|
|
|
133
139
|
resolveLoader
|
|
134
140
|
}
|
|
135
141
|
|
|
136
|
-
module.exports =
|
|
142
|
+
module.exports = webpackConfig
|
package/webpack.config.server.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
const webpack = require('webpack')
|
|
2
2
|
const webpackNodeExternals = require('webpack-node-externals')
|
|
3
3
|
const path = require('path')
|
|
4
|
-
const babelRules = require('./shared/module-rules-babel')
|
|
5
|
-
const manifestLoaderRules = require('./shared/module-rules-manifest-loader')
|
|
6
|
-
const {aliasFromConfig} = require('./shared/resolve-alias')
|
|
7
4
|
|
|
8
|
-
const {config, when, cleanList} = require('./shared')
|
|
9
|
-
const
|
|
5
|
+
const {config, when, cleanList} = require('./shared/index.js')
|
|
6
|
+
const babelRules = require('./shared/module-rules-babel.js')
|
|
7
|
+
const manifestLoaderRules = require('./shared/module-rules-manifest-loader.js')
|
|
8
|
+
const {aliasFromConfig} = require('./shared/resolve-alias.js')
|
|
9
|
+
const {resolveLoader} = require('./shared/resolve-loader.js')
|
|
10
10
|
|
|
11
11
|
const filename = '[name].[chunkhash:8].js'
|
|
12
12
|
|
|
@@ -31,6 +31,7 @@ const webpackConfig = {
|
|
|
31
31
|
},
|
|
32
32
|
optimization: {
|
|
33
33
|
checkWasmTypes: false,
|
|
34
|
+
minimize: true,
|
|
34
35
|
nodeEnv: false
|
|
35
36
|
},
|
|
36
37
|
externals: [webpackNodeExternals()],
|