@s-ui/bundler 8.0.0-beta.2 → 8.0.0-beta.23

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.
@@ -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.3.0 duplicate-package-checker-webpack-plugin@3.0.0'
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(
@@ -6,7 +6,6 @@ const path = require('path')
6
6
  const program = require('commander')
7
7
  const rimraf = require('rimraf')
8
8
  const webpack = require('webpack')
9
- const {minify} = require('terser')
10
9
  const {writeFile} = require('@s-ui/helpers/file')
11
10
 
12
11
  const config = require('../webpack.config.prod')
@@ -39,9 +38,13 @@ program
39
38
  })
40
39
  .parse(process.argv)
41
40
 
42
- const {clean = false, context} = program
41
+ const {
42
+ clean = false,
43
+ context,
44
+ linkPackage: packagesToLink = []
45
+ } = program.opts()
46
+
43
47
  config.context = context || config.context
44
- const packagesToLink = program.linkPackage || []
45
48
 
46
49
  const nextConfig = packagesToLink.length
47
50
  ? linkLoaderConfigBuilder({
@@ -72,7 +75,6 @@ webpack(nextConfig).run(async (error, stats) => {
72
75
  if (stats.hasWarnings()) {
73
76
  const jsonStats = stats.toJson('errors-warnings')
74
77
  log.warn('Webpack generated the following warnings: ')
75
- log.warn(jsonStats.warnings)
76
78
  jsonStats.warnings.map(({message}) => log.warn(message))
77
79
  }
78
80
 
@@ -133,10 +135,9 @@ webpack(nextConfig).run(async (error, stats) => {
133
135
  JSON.stringify(staticsCacheOnly)
134
136
  )
135
137
 
136
- const {code: minifiedSw} = await minify(swCode, {sourceMap: false})
137
138
  const swFilePath = resolvePublicFile('service-worker.js')
138
139
 
139
- await writeFile(swFilePath, minifiedSw)
140
+ await writeFile(swFilePath, swCode)
140
141
  console.log('\nService worker generated succesfully!\n')
141
142
  }
142
143
 
@@ -11,10 +11,7 @@ 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
 
@@ -24,8 +21,9 @@ const createCompiler = require('../factories/createCompiler')
24
21
  const linkLoaderConfigBuilder = require('../loaders/linkLoaderConfigBuilder')
25
22
  const log = require('../shared/log')
26
23
 
27
- const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000
28
- const HOST = process.env.HOST || '0.0.0.0'
24
+ const {CI = false, HOST = '0.0.0.0', HTTPS, PORT} = process.env
25
+ const DEFAULT_PORT = +PORT || 3000
26
+ const DEFAULT_WATCH = !CI
29
27
 
30
28
  if (!module.parent) {
31
29
  program
@@ -43,6 +41,11 @@ if (!module.parent) {
43
41
  },
44
42
  []
45
43
  )
44
+ .option(
45
+ '-w, --watch',
46
+ 'Watch files and restart the server on change',
47
+ DEFAULT_WATCH
48
+ )
46
49
  .on('--help', () => {
47
50
  console.log(' Examples:')
48
51
  console.log('')
@@ -52,13 +55,15 @@ if (!module.parent) {
52
55
  console.log('')
53
56
  })
54
57
  .parse(process.argv)
55
- const {context} = program
58
+
59
+ const {context} = program.opts()
60
+
56
61
  webpackConfig.context = context || webpackConfig.context
57
62
  }
58
63
 
59
64
  const start = async ({
60
65
  config = webpackConfig,
61
- packagesToLink = program.linkPackage || []
66
+ packagesToLink = program.opts().linkPackage || []
62
67
  } = {}) => {
63
68
  clearConsole()
64
69
  // Warn and crash if required files are missing
@@ -73,14 +78,16 @@ const start = async ({
73
78
  )
74
79
  process.exit(1)
75
80
  }
76
- const protocol = process.env.HTTPS === 'true' ? 'https' : 'http'
77
- const port = await choosePort(HOST, DEFAULT_PORT)
81
+
82
+ const protocol = HTTPS === 'true' ? 'https' : 'http'
83
+ const port = await choosePort(DEFAULT_PORT)
78
84
  const urls = prepareUrls(protocol, HOST, port)
79
85
  const nextConfig = linkLoaderConfigBuilder({
80
86
  config,
81
- linkAll: program.linkAll,
87
+ linkAll: program.opts().linkAll,
82
88
  packagesToLink
83
89
  })
90
+
84
91
  const compiler = createCompiler(nextConfig, urls)
85
92
  const serverConfig = createDevServerConfig(nextConfig, urls.lanUrlForConfig)
86
93
  const devServer = new WebpackDevServer(
@@ -91,6 +98,7 @@ const start = async ({
91
98
  },
92
99
  compiler
93
100
  )
101
+
94
102
  log.processing('❯ Starting the development server...\n')
95
103
  devServer.startCallback(err => {
96
104
  if (err) return log.error(err)
@@ -35,7 +35,7 @@ const {
35
35
  path: publicPath,
36
36
  args: [entry],
37
37
  root = false
38
- } = program
38
+ } = program.opts()
39
39
 
40
40
  if (!output) {
41
41
  showError(new Error('--output is mandatory.'), program)
@@ -1,12 +1,20 @@
1
1
  // @ts-check
2
2
 
3
- const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware')
4
- const ignoredFiles = require('react-dev-utils/ignoredFiles')
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
+ const getWatchOptions = ({context, watch}) => {
11
+ return watch
12
+ ? {
13
+ ignored: ignoredFiles(context)
14
+ }
15
+ : false
16
+ }
17
+
10
18
  module.exports = config => ({
11
19
  allowedHosts: 'all',
12
20
  client: {
@@ -19,9 +27,7 @@ module.exports = config => ({
19
27
  },
20
28
  static: {
21
29
  directory: 'public',
22
- watch: {
23
- ignored: ignoredFiles(config.context)
24
- }
30
+ watch: getWatchOptions(config)
25
31
  },
26
32
  hot: true,
27
33
  https: protocol === 'https',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@s-ui/bundler",
3
- "version": "8.0.0-beta.2",
3
+ "version": "8.0.0-beta.23",
4
4
  "description": "Config-free bundler for ES6 React apps.",
5
5
  "bin": {
6
6
  "sui-bundler": "./bin/sui-bundler.js"
@@ -21,30 +21,35 @@
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.0",
24
+ "@babel/core": "7.16.7",
25
25
  "@s-ui/helpers": "1",
26
26
  "@s-ui/sass-loader": "1",
27
- "autoprefixer": "10.4.0",
27
+ "address": "1.1.2",
28
+ "autoprefixer": "10.4.2",
28
29
  "babel-loader": "8.2.3",
29
30
  "babel-preset-sui": "3",
30
- "commander": "6.2.1",
31
+ "buffer": "6.0.3",
32
+ "commander": "8.3.0",
31
33
  "css-loader": "6.5.1",
32
- "css-minimizer-webpack-plugin": "3.1.3",
33
- "esbuild-loader": "2.16.0",
34
- "fast-glob": "3.2.7",
34
+ "css-minimizer-webpack-plugin": "3.3.1",
35
+ "esbuild-loader": "2.18.0",
36
+ "escape-string-regexp": "4.0.0",
37
+ "fast-glob": "3.2.10",
38
+ "find-free-ports": "3.0.0",
35
39
  "html-webpack-plugin": "5.5.0",
36
- "mini-css-extract-plugin": "2.4.4",
40
+ "mini-css-extract-plugin": "2.4.6",
41
+ "postcss": "8.4.5",
42
+ "postcss-loader": "6.2.1",
37
43
  "process": "0.11.10",
38
- "postcss": "8.3.11",
39
- "postcss-loader": "6.2.0",
40
- "react-dev-utils": "11.0.4",
41
44
  "rimraf": "3.0.2",
42
- "sass": "1.43.4",
45
+ "sass": "1.47.0",
43
46
  "speed-measure-webpack-plugin": "1.5.0",
47
+ "strip-ansi": "6.0.1",
44
48
  "style-loader": "3.3.1",
45
- "webpack": "5.61.0",
46
- "webpack-dev-server": "4.4.0",
47
- "webpack-manifest-plugin": "4.0.2",
49
+ "url": "0.11.0",
50
+ "webpack": "5.66.0",
51
+ "webpack-dev-server": "4.7.3",
52
+ "webpack-manifest-plugin": "4.1.1",
48
53
  "webpack-node-externals": "3.0.0"
49
54
  }
50
55
  }
@@ -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')
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
+ }
@@ -5,17 +5,26 @@ const webpack = require('webpack')
5
5
  const HtmlWebpackPlugin = require('html-webpack-plugin')
6
6
  const SpeedMeasurePlugin = require('speed-measure-webpack-plugin')
7
7
 
8
- const definePlugin = require('./shared/define')
9
- const manifestLoaderRules = require('./shared/module-rules-manifest-loader')
10
- const {aliasFromConfig, defaultAlias} = require('./shared/resolve-alias')
11
- const {envVars, MAIN_ENTRY_POINT, config, cleanList, when} = require('./shared')
12
- const {resolveLoader} = require('./shared/resolve-loader')
8
+ const {
9
+ envVars,
10
+ MAIN_ENTRY_POINT,
11
+ config,
12
+ cleanList,
13
+ when
14
+ } = require('./shared/index.js')
15
+ const definePlugin = require('./shared/define.js')
16
+ const manifestLoaderRules = require('./shared/module-rules-manifest-loader.js')
17
+ const {aliasFromConfig, defaultAlias} = require('./shared/resolve-alias.js')
18
+
19
+ const {resolveLoader} = require('./shared/resolve-loader.js')
13
20
 
14
21
  const EXCLUDED_FOLDERS_REGEXP = new RegExp(
15
22
  `node_modules(?!${path.sep}@s-ui(${path.sep}studio)(${path.sep}workbench)?${path.sep}src)`
16
23
  )
17
24
  const outputPath = path.join(process.cwd(), 'dist')
18
25
 
26
+ const {CI = false} = process.env
27
+
19
28
  process.env.NODE_ENV = 'development'
20
29
 
21
30
  const smp = new SpeedMeasurePlugin()
@@ -32,14 +41,16 @@ const webpackConfig = {
32
41
  ...aliasFromConfig
33
42
  },
34
43
  fallback: {
35
- fs: false
44
+ fs: false,
45
+ buffer: require.resolve('buffer/'),
46
+ url: require.resolve('url/')
36
47
  },
37
48
  modules: ['node_modules', path.resolve(process.cwd())],
38
49
  extensions: ['.js', '.json']
39
50
  },
40
51
  stats: 'errors-only',
41
52
  entry: cleanList([
42
- require.resolve('react-dev-utils/webpackHotDevClient'),
53
+ require.resolve('./utils/webpackHotDevClient.js'),
43
54
  MAIN_ENTRY_POINT
44
55
  ]),
45
56
  target: 'web',
@@ -116,7 +127,7 @@ const webpackConfig = {
116
127
  )
117
128
  ])
118
129
  },
119
- watch: true,
130
+ watch: !CI,
120
131
  devtool:
121
132
  config.sourcemaps && config.sourcemaps.dev ? config.sourcemaps.dev : false
122
133
  }
@@ -47,7 +47,12 @@ const webpackConfig = {
47
47
  resolve: {
48
48
  alias: {...aliasFromConfig},
49
49
  extensions: ['.js', '.json'],
50
- modules: ['node_modules', path.resolve(process.cwd())]
50
+ modules: ['node_modules', path.resolve(process.cwd())],
51
+ fallback: {
52
+ assert: false,
53
+ fs: false,
54
+ path: false
55
+ }
51
56
  },
52
57
  entry: MAIN_ENTRY_POINT,
53
58
  output: {
@@ -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 {resolveLoader} = require('./shared/resolve-loader')
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