@ideasonpurpose/build-tools-wordpress 1.1.5 → 1.1.7
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 +13 -0
- package/README.md +14 -5
- package/bin/port-reporter.js +1 -1
- package/bin/zip.js +227 -0
- package/example/webpack.config.js +593 -0
- package/lib/AfterDoneReporterPlugin.js +26 -1
- package/lib/WatchRunReporterPlugin.js +1 -1
- package/lib/buildConfig.js +3 -2
- package/lib/devserver-proxy.js +38 -75
- package/lib/find-local-docker-port.js +26 -7
- package/package.json +28 -23
- package/test/devserver-proxy.test.ts +297 -0
- package/test/find-local-docker-port.test.ts +39 -0
- package/vitest.config.ts +18 -0
|
@@ -0,0 +1,593 @@
|
|
|
1
|
+
import { posix as path } from "path";
|
|
2
|
+
|
|
3
|
+
import { statSync } from "fs";
|
|
4
|
+
import { cosmiconfig, cosmiconfigSync } from "cosmiconfig";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
|
|
7
|
+
import MiniCssExtractPlugin from "mini-css-extract-plugin";
|
|
8
|
+
import { EsbuildPlugin } from "esbuild-loader";
|
|
9
|
+
|
|
10
|
+
import CopyPlugin from "copy-webpack-plugin";
|
|
11
|
+
import { BundleAnalyzerPlugin } from "webpack-bundle-analyzer";
|
|
12
|
+
import ImageMinimizerPlugin from "image-minimizer-webpack-plugin";
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
AfterDoneReporterPlugin,
|
|
16
|
+
buildConfig,
|
|
17
|
+
DependencyManifestPlugin,
|
|
18
|
+
devserverProxy,
|
|
19
|
+
findLocalPort,
|
|
20
|
+
WatchRunReporterPlugin,
|
|
21
|
+
} from "@ideasonpurpose/build-tools-wordpress";
|
|
22
|
+
|
|
23
|
+
import autoprefixer from "autoprefixer";
|
|
24
|
+
import cssnano from "cssnano";
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Sass flavors for conditional sass-loader implementations
|
|
28
|
+
*/
|
|
29
|
+
import * as nodeSass from "sass";
|
|
30
|
+
import * as dartSass from "sass-embedded";
|
|
31
|
+
|
|
32
|
+
// Experimenting with this
|
|
33
|
+
import DependencyExtractionWebpackPlugin from "@wordpress/dependency-extraction-webpack-plugin";
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Force `mode: production` when running the analyzer
|
|
37
|
+
* TODO: webpack5 changed env in here, might need to change WEBPACK_BUNDLE_ANALYZER
|
|
38
|
+
*/
|
|
39
|
+
if (process.env.WEBPACK_BUNDLE_ANALYZER) process.env.NODE_ENV = "production";
|
|
40
|
+
|
|
41
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
42
|
+
|
|
43
|
+
const stats = {
|
|
44
|
+
preset: "normal",
|
|
45
|
+
cachedAssets: false,
|
|
46
|
+
assets: true,
|
|
47
|
+
// assetsSpace: 12,
|
|
48
|
+
// context: new URL( import.meta.url).pathname,
|
|
49
|
+
// all: true,
|
|
50
|
+
// assets: true,
|
|
51
|
+
// builtAt: true,
|
|
52
|
+
// cachedModules: true,
|
|
53
|
+
// children: false, // Adds a bunch of blank lines to stats output
|
|
54
|
+
// chunkGroups: false,
|
|
55
|
+
// chunkModules: false,
|
|
56
|
+
// chunkOrigins: true,
|
|
57
|
+
// chunkRelations: true,
|
|
58
|
+
// chunks: false,
|
|
59
|
+
// colors: true,
|
|
60
|
+
// depth: false,
|
|
61
|
+
// env: true,
|
|
62
|
+
// orphanModules: false,
|
|
63
|
+
// dependentModules: true,
|
|
64
|
+
modules: false,
|
|
65
|
+
groupAssetsByChunk: true,
|
|
66
|
+
entrypoints: true,
|
|
67
|
+
// // errorDetails: "auto",
|
|
68
|
+
children: false,
|
|
69
|
+
// errorDetails: true,
|
|
70
|
+
errors: true,
|
|
71
|
+
errorStack: true,
|
|
72
|
+
// excludeAssets: [/hot-update/, /_sock-/],
|
|
73
|
+
// groupAssetsByChunk: true,
|
|
74
|
+
// logging: "warn",
|
|
75
|
+
// optimizationBailout: true,
|
|
76
|
+
// loggingTrace: false,
|
|
77
|
+
performance: true,
|
|
78
|
+
reasons: true,
|
|
79
|
+
relatedAssets: true,
|
|
80
|
+
timings: true,
|
|
81
|
+
version: true,
|
|
82
|
+
warnings: true,
|
|
83
|
+
loggingDebug: ["sass-loader"],
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export default async (env) => {
|
|
87
|
+
// const siteDir = new URL("../site", import.meta.url).pathname;
|
|
88
|
+
const siteDir = new URL(import.meta.url).pathname;
|
|
89
|
+
// const explorerSync = cosmiconfigSync("ideasonpurpose");
|
|
90
|
+
const explorer = cosmiconfig("ideasonpurpose");
|
|
91
|
+
// const configFile = explorerSync.search(siteDir);
|
|
92
|
+
const configFile = await explorer.search(siteDir);
|
|
93
|
+
|
|
94
|
+
// import buildConfig from "./lib/buildConfig.js";
|
|
95
|
+
// console.log({ siteDir, configFile, nm: path.resolve("node_modules") });
|
|
96
|
+
|
|
97
|
+
const config = await buildConfig(configFile);
|
|
98
|
+
|
|
99
|
+
setTimeout(() =>
|
|
100
|
+
console.log(
|
|
101
|
+
chalk.magenta.bold("sass implementation"),
|
|
102
|
+
chalk.yellow.bold(config.sass),
|
|
103
|
+
config.sass === "sass" ? nodeSass : dartSass,
|
|
104
|
+
),
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* `usePolling` is a placeholder, try and detect native Windows Docker mounts
|
|
109
|
+
* since they don't support file-watching (no inotify events), if there's
|
|
110
|
+
* something clean, use that instead. For now, this will force-enable polling.
|
|
111
|
+
*
|
|
112
|
+
* TODO: Why so much dancing around defaults when this could just inherit from default.config?
|
|
113
|
+
*/
|
|
114
|
+
const usePolling = Boolean(config.usePolling);
|
|
115
|
+
const pollInterval = Math.max(
|
|
116
|
+
parseInt(config.pollInterval, 10) || parseInt(config.usePolling, 10) || 400,
|
|
117
|
+
400,
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
const devtool = config.devtool || false;
|
|
121
|
+
|
|
122
|
+
console.log({ config, devServerProxy: await devserverProxy(config) });
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
// stats: "errors-warnings",
|
|
126
|
+
stats,
|
|
127
|
+
module: {
|
|
128
|
+
rules: [
|
|
129
|
+
// {
|
|
130
|
+
// test: /\.(js|jsx|mjs)$/,
|
|
131
|
+
// include: [
|
|
132
|
+
// path.resolve(config.src),
|
|
133
|
+
// path.resolve("../tools/node_modules"),
|
|
134
|
+
// path.resolve("../site/node_modules"),
|
|
135
|
+
// ],
|
|
136
|
+
// exclude: function (module) {
|
|
137
|
+
// const moduleRegex = new RegExp(
|
|
138
|
+
// `node_modules/(${config.transpileDependencies.join("|")})`
|
|
139
|
+
// );
|
|
140
|
+
// return /node_modules/.test(module) && !moduleRegex.test(module);
|
|
141
|
+
// },
|
|
142
|
+
|
|
143
|
+
// /**
|
|
144
|
+
// * EXPERIMENTAL!!
|
|
145
|
+
// * If JS compilation breaks, try reverting this first.
|
|
146
|
+
// */
|
|
147
|
+
// loader: "esbuild-loader",
|
|
148
|
+
// options: {
|
|
149
|
+
// loader: "jsx",
|
|
150
|
+
// target: "es2015",
|
|
151
|
+
// },
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Updated 2022-09, simpler
|
|
155
|
+
*/
|
|
156
|
+
{
|
|
157
|
+
test: /\.m?jsx?$/,
|
|
158
|
+
loader: "esbuild-loader",
|
|
159
|
+
options: {
|
|
160
|
+
loader: "jsx",
|
|
161
|
+
target: "es2015",
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
test: /\.tsx?$/,
|
|
166
|
+
loader: "esbuild-loader",
|
|
167
|
+
options: {
|
|
168
|
+
loader: "tsx",
|
|
169
|
+
target: "es2015",
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
|
|
173
|
+
// use: {
|
|
174
|
+
// loader: "babel-loader",
|
|
175
|
+
// options: {
|
|
176
|
+
// cacheDirectory: !isProduction,
|
|
177
|
+
// sourceType: "unambiguous",
|
|
178
|
+
// plugins: [
|
|
179
|
+
// "@babel/plugin-syntax-dynamic-import",
|
|
180
|
+
// ...(isProduction
|
|
181
|
+
// ? []
|
|
182
|
+
// : ["@babel/plugin-transform-react-jsx-source"]),
|
|
183
|
+
// ],
|
|
184
|
+
// presets: [
|
|
185
|
+
// [
|
|
186
|
+
// "@babel/preset-env",
|
|
187
|
+
// {
|
|
188
|
+
// forceAllTransforms: true,
|
|
189
|
+
// useBuiltIns: "usage",
|
|
190
|
+
// configPath: config.src,
|
|
191
|
+
// corejs: 3,
|
|
192
|
+
// modules: false,
|
|
193
|
+
// debug: false,
|
|
194
|
+
// },
|
|
195
|
+
// ],
|
|
196
|
+
// "@babel/preset-react",
|
|
197
|
+
// ],
|
|
198
|
+
// },
|
|
199
|
+
// },
|
|
200
|
+
// },
|
|
201
|
+
{
|
|
202
|
+
test: /\.(scss|css)$/,
|
|
203
|
+
use: [
|
|
204
|
+
{ loader: MiniCssExtractPlugin.loader },
|
|
205
|
+
{
|
|
206
|
+
loader: "css-loader",
|
|
207
|
+
options: {
|
|
208
|
+
import: false, // imports already handled by Sass or PostCSS
|
|
209
|
+
// sourceMap: !isProduction,
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
loader: "postcss-loader",
|
|
214
|
+
options: {
|
|
215
|
+
postcssOptions: {
|
|
216
|
+
plugins: isProduction
|
|
217
|
+
? [
|
|
218
|
+
autoprefixer,
|
|
219
|
+
cssnano({ preset: ["default", { colormin: false }] }),
|
|
220
|
+
]
|
|
221
|
+
: [autoprefixer],
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
// {
|
|
226
|
+
// loader: "resolve-url-loader",
|
|
227
|
+
// options: {
|
|
228
|
+
// // sourceMap: true,
|
|
229
|
+
// // debug: true,
|
|
230
|
+
// },
|
|
231
|
+
// },
|
|
232
|
+
{
|
|
233
|
+
loader: "sass-loader",
|
|
234
|
+
options: {
|
|
235
|
+
implementation: config.sass === "sass" ? nodeSass : dartSass,
|
|
236
|
+
// implementation: nodeSass,
|
|
237
|
+
// implementation: await import(config.sass),
|
|
238
|
+
sourceMap: !isProduction,
|
|
239
|
+
warnRuleAsWarning: true,
|
|
240
|
+
webpackImporter: false,
|
|
241
|
+
sassOptions: {
|
|
242
|
+
// api: "modern",
|
|
243
|
+
|
|
244
|
+
includePaths: [
|
|
245
|
+
path.resolve(config.src, "sass"),
|
|
246
|
+
// path.resolve("../site/node_modules"),
|
|
247
|
+
path.resolve("node_modules"),
|
|
248
|
+
],
|
|
249
|
+
style: "expanded",
|
|
250
|
+
verbose: true,
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
],
|
|
255
|
+
},
|
|
256
|
+
/**
|
|
257
|
+
* This image loader is specifically for images which are required or
|
|
258
|
+
* imported into a webpack processed entry file. Optimization is
|
|
259
|
+
* handled by image-minimizer-webpack-plugin. These assets will be
|
|
260
|
+
* renamed with a chunkhash fragment.
|
|
261
|
+
*
|
|
262
|
+
* All images under `config.src` will be optimized and copied by
|
|
263
|
+
* copy-webpack-plugin but will keep their original filenames and
|
|
264
|
+
* relative paths. Images included in SCSS files will be processed
|
|
265
|
+
* twice, once with a hashed name and again with its original name.
|
|
266
|
+
*/
|
|
267
|
+
{
|
|
268
|
+
test: /\.(jpe?g|png|gif|tif|webp|avif)$/i,
|
|
269
|
+
type: "asset",
|
|
270
|
+
},
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* SVGs can be imported as asset urls or React components
|
|
274
|
+
*
|
|
275
|
+
* To import an SVG file as a src url, append ?url to the filename:
|
|
276
|
+
* import svg from './assets/file.svg?url'
|
|
277
|
+
*
|
|
278
|
+
* To import an SVG file as a React component
|
|
279
|
+
|
|
280
|
+
* @link https://react-svgr.com/docs/webpack/#use-svgr-and-asset-svg-in-the-same-project
|
|
281
|
+
*/
|
|
282
|
+
{
|
|
283
|
+
test: /\.svg$/i,
|
|
284
|
+
type: "asset",
|
|
285
|
+
resourceQuery: /url/, // *.svg?url
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
test: /\.svg$/i,
|
|
289
|
+
issuer: /\.[jt]sx?$/,
|
|
290
|
+
resourceQuery: { not: [/url/] }, // exclude react component if *.svg?url
|
|
291
|
+
use: ["@svgr/webpack"],
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
test: /fonts\/.*\.(ttf|eot|woff2?)$/i,
|
|
295
|
+
type: "asset",
|
|
296
|
+
},
|
|
297
|
+
],
|
|
298
|
+
},
|
|
299
|
+
|
|
300
|
+
context: path.resolve(config.src),
|
|
301
|
+
|
|
302
|
+
resolve: {
|
|
303
|
+
modules: [
|
|
304
|
+
path.resolve("../tools/node_modules"),
|
|
305
|
+
path.resolve("../site/node_modules"),
|
|
306
|
+
path.resolve("./node_modules"),
|
|
307
|
+
],
|
|
308
|
+
},
|
|
309
|
+
|
|
310
|
+
resolveLoader: {
|
|
311
|
+
modules: [
|
|
312
|
+
path.resolve("../tools/node_modules"),
|
|
313
|
+
path.resolve("./node_modules"), // for local development when running outside of Docker
|
|
314
|
+
],
|
|
315
|
+
},
|
|
316
|
+
|
|
317
|
+
entry: config.entry,
|
|
318
|
+
|
|
319
|
+
output: {
|
|
320
|
+
path: new URL(config.dist, import.meta.url).pathname,
|
|
321
|
+
/**
|
|
322
|
+
* Primary output filenames SHOULD NOT include hashes in development because
|
|
323
|
+
* some files are written to disk from devServer middleware. Because those
|
|
324
|
+
* files are written outside standard webpack output, they aren't cleaned
|
|
325
|
+
* up by standard webpack cleaning functions.
|
|
326
|
+
*/
|
|
327
|
+
filename: isProduction ? "[name]-[contenthash:8].js" : "[name].js",
|
|
328
|
+
chunkFilename: "[id]-[chunkhash:8].js",
|
|
329
|
+
publicPath: config.publicPath,
|
|
330
|
+
/**
|
|
331
|
+
* Assets are not cleaned when writeToDisk is true in devServer
|
|
332
|
+
* Works correctly with builds.
|
|
333
|
+
* @link https://github.com/webpack/webpack-dev-middleware/issues/861
|
|
334
|
+
*/
|
|
335
|
+
clean: true,
|
|
336
|
+
},
|
|
337
|
+
|
|
338
|
+
devServer: {
|
|
339
|
+
host: "0.0.0.0",
|
|
340
|
+
allowedHosts: "all",
|
|
341
|
+
// setupExitSignals: true,// default
|
|
342
|
+
|
|
343
|
+
compress: config.devServerCompress || false, // TODO: True by default in devServer v4, exposed via config.devServerCompress to test speed impact
|
|
344
|
+
port: "auto",
|
|
345
|
+
// hot: true, // TODO: What does 'only' do? https://webpack.js.org/configuration/dev-server/#devserverhot
|
|
346
|
+
hot: 'only', // TODO: What does 'only' do? https://webpack.js.org/configuration/dev-server/#devserverhot
|
|
347
|
+
client: {
|
|
348
|
+
// logging: "error", // TODO: New, is this ok?
|
|
349
|
+
logging: "info", // TODO: New, is this ok?
|
|
350
|
+
overlay: true, // { warnings: true, errors: true },
|
|
351
|
+
progress: true, // TODO: New, is this ok?
|
|
352
|
+
reconnect: 30,
|
|
353
|
+
// webSocketURL: {
|
|
354
|
+
// port: parseInt(process.env.PORT), // external port, so websockets hit the right endpoint
|
|
355
|
+
// },
|
|
356
|
+
},
|
|
357
|
+
// webSocketServer: "ws",
|
|
358
|
+
// static: {
|
|
359
|
+
// // TODO: Should contentBase be `false` when there's a proxy?
|
|
360
|
+
// directory: path.join("/usr/src/site/", config.contentBase),
|
|
361
|
+
// /*
|
|
362
|
+
// * TODO: Poll options were enabled as a workaround for Docker-win volume inotify
|
|
363
|
+
// * issues. Looking to make this conditional...
|
|
364
|
+
// * Maybe defined `isWindows` or `hasiNotify` for assigning a value
|
|
365
|
+
// * Placeholder defined at the top of the file.
|
|
366
|
+
// * For now, `usePolling` is a boolean (set to true)
|
|
367
|
+
// * ref: https://github.com/docker/for-win/issues/56
|
|
368
|
+
// * https://www.npmjs.com/package/is-windows
|
|
369
|
+
// * TODO: Safe to remove?
|
|
370
|
+
// * TODO: Test on vanilla Windows (should now work in WSL)
|
|
371
|
+
// */
|
|
372
|
+
|
|
373
|
+
// watch: {
|
|
374
|
+
// poll: usePolling && pollInterval,
|
|
375
|
+
// ignored: ["node_modules", "vendor"],
|
|
376
|
+
// },
|
|
377
|
+
// },
|
|
378
|
+
|
|
379
|
+
devMiddleware: {
|
|
380
|
+
index: false, // enable root proxying
|
|
381
|
+
|
|
382
|
+
writeToDisk: (filePath) => {
|
|
383
|
+
/**
|
|
384
|
+
* Note: If this is an async function, it will write everything to disk
|
|
385
|
+
*
|
|
386
|
+
* Never write hot-update files to disk.
|
|
387
|
+
*/
|
|
388
|
+
// vendors-node_modules_mini-css-extract-plugin_dist_hmr_hotModuleReplacement_js-node_modules_we-780fe4.js.map
|
|
389
|
+
if (/.+(hot-update)\.(js|json|js\.map)$/.test(filePath)) {
|
|
390
|
+
return false;
|
|
391
|
+
}
|
|
392
|
+
// SHORT_CIRCUIT FOR TESTING
|
|
393
|
+
return true;
|
|
394
|
+
|
|
395
|
+
if (/.+\.(svg|json|php|jpg|png)$/.test(filePath)) {
|
|
396
|
+
const fileStat = statSync(filePath, { throwIfNoEntry: false });
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Always write SVG, PHP & JSON files
|
|
400
|
+
*/
|
|
401
|
+
if (/.+\.(svg|json|php)$/.test(filePath)) {
|
|
402
|
+
return true;
|
|
403
|
+
} else {
|
|
404
|
+
/**
|
|
405
|
+
* Write any images under 100k and anything not yet on disk
|
|
406
|
+
*/
|
|
407
|
+
if (!fileStat || fileStat.size < 100 * 1024) {
|
|
408
|
+
return true;
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* TODO: This might all be unnecessary. Webpack seems to be doing a good job with its native caching
|
|
412
|
+
*/
|
|
413
|
+
// const randOffset = Math.random() * 300000; // 0-5 minutes
|
|
414
|
+
// const expired = new Date() - fileStat.mtime > randOffset;
|
|
415
|
+
// const relPath = filePath.replace(config.dist, "dist");
|
|
416
|
+
// if (expired) {
|
|
417
|
+
// console.log("DEBUG writeToDisk:", { replacing: relPath });
|
|
418
|
+
// return true;
|
|
419
|
+
// }
|
|
420
|
+
// console.log("DEBUG writeToDisk:", { cached: relPath });
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
return false;
|
|
424
|
+
},
|
|
425
|
+
// stats,
|
|
426
|
+
// stats: 'verbose',
|
|
427
|
+
},
|
|
428
|
+
|
|
429
|
+
// NOTE: trying to make injection conditional so wp-admin stops reloading
|
|
430
|
+
// injectClient: compilerConfig => {
|
|
431
|
+
// console.log(compilerConfig);
|
|
432
|
+
// return true;
|
|
433
|
+
// },
|
|
434
|
+
|
|
435
|
+
onListening: (devServer) => {
|
|
436
|
+
const port = devServer.server.address().port;
|
|
437
|
+
devServer.compiler.options.devServer.port =
|
|
438
|
+
devServer.server.address().port;
|
|
439
|
+
devServer.compiler._devServer = devServer;
|
|
440
|
+
|
|
441
|
+
console.log("Listening on port:", port);
|
|
442
|
+
},
|
|
443
|
+
|
|
444
|
+
setupMiddlewares: (middlewares, devServer) => {
|
|
445
|
+
// devServer.compiler.options.devServer.port = devServer.options.port;
|
|
446
|
+
// devServer.compiler._devServer = devServer;
|
|
447
|
+
// if (!devServer) {
|
|
448
|
+
// throw new Error("webpack-dev-server is not defined");
|
|
449
|
+
// }
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* The `/inform` route is an annoying bit of code. Here's why:
|
|
453
|
+
* Ubiquity Wi-fi hardware frequently spams the shit out of their
|
|
454
|
+
* networks, specifically requesting the `/inform` route from
|
|
455
|
+
* every device. We still have some Ubiquity hardware on our
|
|
456
|
+
* networks, so dev servers were constantly responding to
|
|
457
|
+
* `/inform` requests with 404s, filling logs and cluttering
|
|
458
|
+
* terminals. So that's why this is here. I hate it.
|
|
459
|
+
*/
|
|
460
|
+
devServer.app.all("/inform", () => false);
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* The "/webpack/reload" endpoint will trigger a full devServer refresh
|
|
464
|
+
* Originally from our Browsersync implementation:
|
|
465
|
+
*
|
|
466
|
+
* https://github.com/ideasonpurpose/wp-theme-init/blob/ad8039c9757ffc3a0a0ed0adcc616a013fdc8604/src/ThemeInit.php#L202
|
|
467
|
+
*/
|
|
468
|
+
devServer.app.get("/webpack/reload", (req, res) => {
|
|
469
|
+
console.log(
|
|
470
|
+
chalk.yellow("Reload triggered by request to /webpack/reload"),
|
|
471
|
+
);
|
|
472
|
+
|
|
473
|
+
devServer.sendMessage(
|
|
474
|
+
devServer.webSocketServer.clients,
|
|
475
|
+
"content-changed",
|
|
476
|
+
);
|
|
477
|
+
res.json({ status: "Reloading!" });
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
return middlewares;
|
|
481
|
+
},
|
|
482
|
+
|
|
483
|
+
watchFiles: {
|
|
484
|
+
paths: [
|
|
485
|
+
path.resolve(config.src, "../**/*.{php,json}"), // WordPress
|
|
486
|
+
// path.resolve(config.src, `../${config.contentBase}/*.html`), // Jekyll
|
|
487
|
+
],
|
|
488
|
+
options: {
|
|
489
|
+
ignored: ["**/.git/**", "**/vendor/**", "**/node_modules/**", "**/dist/**"],
|
|
490
|
+
ignoreInitial: true,
|
|
491
|
+
ignorePermissionErrors: true,
|
|
492
|
+
/**
|
|
493
|
+
* TODO: Can polling be removed everywhere?
|
|
494
|
+
* @link https://github.com/docker/for-win/issues/56#issuecomment-576749639
|
|
495
|
+
*/
|
|
496
|
+
usePolling,
|
|
497
|
+
interval: pollInterval,
|
|
498
|
+
},
|
|
499
|
+
},
|
|
500
|
+
|
|
501
|
+
...(await devserverProxy(config)),
|
|
502
|
+
},
|
|
503
|
+
|
|
504
|
+
mode: isProduction ? "production" : "development",
|
|
505
|
+
|
|
506
|
+
performance: {
|
|
507
|
+
hints: isProduction ? "warning" : false,
|
|
508
|
+
},
|
|
509
|
+
|
|
510
|
+
devtool,
|
|
511
|
+
|
|
512
|
+
plugins: [
|
|
513
|
+
new MiniCssExtractPlugin({
|
|
514
|
+
filename: isProduction ? "[name]-[contenthash:8].css" : "[name].css",
|
|
515
|
+
}),
|
|
516
|
+
|
|
517
|
+
new CopyPlugin({
|
|
518
|
+
patterns: [
|
|
519
|
+
{
|
|
520
|
+
from: "**/*",
|
|
521
|
+
globOptions: {
|
|
522
|
+
dot: true, // TODO: Dangerous? Why is this ever necessary?!
|
|
523
|
+
ignore: [
|
|
524
|
+
"**/{.gitignore,.DS_Store,*:Zone.Identifier}",
|
|
525
|
+
config.src + "/{blocks,fonts,js,sass}/**",
|
|
526
|
+
],
|
|
527
|
+
},
|
|
528
|
+
},
|
|
529
|
+
],
|
|
530
|
+
options: { concurrency: 50 },
|
|
531
|
+
}),
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* @link https://developer.wordpress.org/block-editor/reference-guides/packages/packages-dependency-extraction-webpack-plugin/
|
|
535
|
+
*/
|
|
536
|
+
new DependencyExtractionWebpackPlugin(),
|
|
537
|
+
|
|
538
|
+
new DependencyManifestPlugin({
|
|
539
|
+
writeManifestFile: true,
|
|
540
|
+
manifestFile: config.manifestFile,
|
|
541
|
+
}),
|
|
542
|
+
|
|
543
|
+
new WatchRunReporterPlugin(),
|
|
544
|
+
|
|
545
|
+
new AfterDoneReporterPlugin({
|
|
546
|
+
echo: env && env.WEBPACK_SERVE,
|
|
547
|
+
// message:
|
|
548
|
+
// "Dev site " + chalk.blue.bold(`http://localhost:${process.env.PORT}`),
|
|
549
|
+
}),
|
|
550
|
+
|
|
551
|
+
new BundleAnalyzerPlugin({
|
|
552
|
+
analyzerMode: isProduction ? "static" : "disabled",
|
|
553
|
+
openAnalyzer: false,
|
|
554
|
+
reportFilename: path.resolve(siteDir, "webpack/stats/index.html"),
|
|
555
|
+
}),
|
|
556
|
+
],
|
|
557
|
+
optimization: {
|
|
558
|
+
splitChunks: {
|
|
559
|
+
chunks: "all",
|
|
560
|
+
},
|
|
561
|
+
minimizer: [
|
|
562
|
+
new EsbuildPlugin({
|
|
563
|
+
/**
|
|
564
|
+
* Additional targets, can we bump this up to es2020 yet?
|
|
565
|
+
* TODO: Expose this to the config
|
|
566
|
+
* @link https://esbuild.github.io/content-types/#javascript
|
|
567
|
+
*/
|
|
568
|
+
target: "es2015",
|
|
569
|
+
}),
|
|
570
|
+
new ImageMinimizerPlugin({
|
|
571
|
+
severityError: "error",
|
|
572
|
+
|
|
573
|
+
minimizer: {
|
|
574
|
+
implementation: ImageMinimizerPlugin.sharpMinify,
|
|
575
|
+
|
|
576
|
+
options: {
|
|
577
|
+
/**
|
|
578
|
+
* Sharp options
|
|
579
|
+
*/
|
|
580
|
+
encodeOptions: {
|
|
581
|
+
jpeg: {
|
|
582
|
+
quality: 70,
|
|
583
|
+
mozjpeg: true,
|
|
584
|
+
},
|
|
585
|
+
png: {},
|
|
586
|
+
},
|
|
587
|
+
},
|
|
588
|
+
},
|
|
589
|
+
}),
|
|
590
|
+
],
|
|
591
|
+
},
|
|
592
|
+
};
|
|
593
|
+
};
|
|
@@ -23,7 +23,16 @@ export class AfterDoneReporterPlugin {
|
|
|
23
23
|
apply(compiler) {
|
|
24
24
|
compiler.hooks.done.tapPromise(this.name, async (stats) => {
|
|
25
25
|
if (this.config.echo) {
|
|
26
|
-
|
|
26
|
+
/**
|
|
27
|
+
* NOTE: As of webpack-dev-server vXX.XX.XXX, auto-assigned ports are
|
|
28
|
+
* not propagated into the compiler.options.devServer object.
|
|
29
|
+
*
|
|
30
|
+
* As a workaround, this relies on the follining line being added to
|
|
31
|
+
* the webpack.config file's devServer.setupMiddlewares method:
|
|
32
|
+
*
|
|
33
|
+
* devServer.compiler.options.devServer.port = devServer.options.port;
|
|
34
|
+
*
|
|
35
|
+
*/
|
|
27
36
|
const { host, port } = compiler.options.devServer;
|
|
28
37
|
const { startTime, endTime, modules, assetsInfo } = stats.compilation;
|
|
29
38
|
const hostname = host === "0.0.0.0" ? "localhost" : host;
|
|
@@ -45,7 +54,23 @@ export class AfterDoneReporterPlugin {
|
|
|
45
54
|
setTimeout(() =>
|
|
46
55
|
console.log("\n" + this.config.prefix + " " + messages),
|
|
47
56
|
);
|
|
57
|
+
|
|
58
|
+
setTimeout(() => {
|
|
59
|
+
// console.log(Object.keys(compiler));
|
|
60
|
+
// console.log(compiler.options);
|
|
61
|
+
});
|
|
48
62
|
}
|
|
49
63
|
});
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
// compiler.hooks.done.tapPromise("webpack-dev-server", async (stats) => {
|
|
67
|
+
// await stats;
|
|
68
|
+
// setTimeout(() => {
|
|
69
|
+
// console.log(chalk.bold.magenta("in webpack-dev-server hook"), {
|
|
70
|
+
// stats, thing: Object.keys( compiler.options),
|
|
71
|
+
// });
|
|
72
|
+
// });
|
|
73
|
+
// });
|
|
74
|
+
|
|
50
75
|
}
|
|
51
76
|
}
|
|
@@ -12,7 +12,7 @@ export class WatchRunReporterPlugin {
|
|
|
12
12
|
const defaults = {
|
|
13
13
|
echo: true,
|
|
14
14
|
prefix: `🟢${chalk.gray("(iop)")}:`,
|
|
15
|
-
message: chalk.bold("Compiling..."),
|
|
15
|
+
message: chalk.bold("Compiling...", ""),
|
|
16
16
|
};
|
|
17
17
|
this.config = { ...defaults, ...options };
|
|
18
18
|
this.name = "IOP Reporter Plugin";
|
package/lib/buildConfig.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from "fs-extra";
|
|
2
2
|
import { posix as path } from "path";
|
|
3
3
|
import chalk from "chalk";
|
|
4
|
+
import url from "url";
|
|
4
5
|
|
|
5
6
|
import { findLocalPort } from "../index.js";
|
|
6
7
|
|
|
@@ -14,7 +15,7 @@ const defaultConfig = {
|
|
|
14
15
|
contentBase: "/dist/", // TODO: Should this be false?
|
|
15
16
|
manifestFile: "./dependency-manifest.json",
|
|
16
17
|
sass: "sass-embedded",
|
|
17
|
-
|
|
18
|
+
devtool: false,
|
|
18
19
|
transpileDependencies: ["ansi-regex", "normalize-url"],
|
|
19
20
|
proxy: "wordpress",
|
|
20
21
|
};
|
|
@@ -87,7 +88,7 @@ export async function buildConfig(configFile = { config: {} }) {
|
|
|
87
88
|
configFile.filepath = configFile.filepath || "../site/placeholder.file";
|
|
88
89
|
config.src = path.resolve(configFile.filepath, "..", config.src);
|
|
89
90
|
config.dist = path.resolve(configFile.filepath, "..", config.dist);
|
|
90
|
-
|
|
91
|
+
config.configFileUrl = url.pathToFileURL(configFile.filepath);
|
|
91
92
|
/**
|
|
92
93
|
* Check for `config.src` and create it if missing
|
|
93
94
|
* TODO: unresolved, create the file? Fail? Throw error?
|