@studyportals/webpack-helper 8.1.0 → 8.2.0-beta.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.
Files changed (29) hide show
  1. package/README.md +404 -389
  2. package/assets/.browserslistrc +2 -2
  3. package/dist/defaults/production.config.js +79 -0
  4. package/{src → dist}/factories/chunks-retry-plugin-factory.js +15 -17
  5. package/dist/interfaces/preset.interface.js +2 -0
  6. package/{src → dist}/model/configuration.js +2 -1
  7. package/{src → dist}/plugins/retry-chunk-load.plugin.js +35 -35
  8. package/dist/utils/cpus.js +29 -0
  9. package/package.json +55 -51
  10. package/src/defaults/production.config.js +0 -59
  11. /package/{src → dist}/defaults/development.config.js +0 -0
  12. /package/{src → dist}/enums/mode.js +0 -0
  13. /package/{src → dist}/enums/preset.js +0 -0
  14. /package/{src → dist}/factories/browser-list-to-esbuild-target-factory.js +0 -0
  15. /package/{src → dist}/factories/configuration-factory.js +0 -0
  16. /package/{src → dist}/interfaces/bob.interface.js +0 -0
  17. /package/{src → dist}/interfaces/chunks-retry.interface.js +0 -0
  18. /package/{src → dist}/interfaces/entry.interface.js +0 -0
  19. /package/{src → dist}/interfaces/entrypoint.interface.js +0 -0
  20. /package/{src/interfaces/output.interface.js → dist/interfaces/minify.interface.js} +0 -0
  21. /package/{src/interfaces/preset.interface.js → dist/interfaces/output.interface.js} +0 -0
  22. /package/{src → dist}/main.js +0 -0
  23. /package/{src → dist}/model/entry.js +0 -0
  24. /package/{src → dist}/model/module.js +0 -0
  25. /package/{src → dist}/model/output.js +0 -0
  26. /package/{src → dist}/model/plugins.js +0 -0
  27. /package/{src → dist}/presets/javascript.preset.js +0 -0
  28. /package/{src → dist}/presets/typescript.preset.js +0 -0
  29. /package/{src → dist}/presets/vue-typescript.preset.js +0 -0
@@ -1,3 +1,3 @@
1
- #extends @studyportals/browserslist-config/clients
2
- #extends @studyportals/browserslist-config/internal
1
+ #extends @studyportals/browserslist-config/clients
2
+ #extends @studyportals/browserslist-config/internal
3
3
  extends @studyportals/browserslist-config/student
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ProductionConfig = void 0;
4
+ const cpus_1 = require("../utils/cpus");
5
+ const browser_list_to_esbuild_target_factory_1 = require("../factories/browser-list-to-esbuild-target-factory");
6
+ const webpack = require('webpack');
7
+ const cssMinimizerPlugin = require('css-minimizer-webpack-plugin');
8
+ const DllAvailabilityTracker = require('@studyportals/dll-availability-tracker');
9
+ const DEFAULT_TERSER_PASSES = 2;
10
+ const ProductionConfig = (bobConfig, minifyConfig = {}) => {
11
+ let dllDependencies = ['library'];
12
+ if (bobConfig && bobConfig.hasOwnProperty('dllPackages')) {
13
+ bobConfig.dllPackages.forEach((dependency) => dllDependencies.push(dependency.manifest.name));
14
+ }
15
+ const parallel = (0, cpus_1.getAvailableCpus)();
16
+ return {
17
+ plugins: [
18
+ new webpack.DefinePlugin({
19
+ 'process.env': {
20
+ NODE_ENV: '"production"'
21
+ }
22
+ }),
23
+ minifyConfig.css !== 'lightningcss'
24
+ ? new cssMinimizerPlugin({
25
+ parallel,
26
+ minimizerOptions: {
27
+ preset: [
28
+ 'default',
29
+ {
30
+ discardComments: {
31
+ removeAll: true
32
+ }
33
+ }
34
+ ]
35
+ },
36
+ })
37
+ : new cssMinimizerPlugin({
38
+ parallel,
39
+ minify: cssMinimizerPlugin.lightningCssMinify
40
+ }),
41
+ new DllAvailabilityTracker({
42
+ dependencies: dllDependencies || []
43
+ })
44
+ ],
45
+ optimization: {
46
+ minimize: true,
47
+ minimizer: [
48
+ compiler => {
49
+ console.log(`webpack-helper: minifying JS with ${minifyConfig.minifier || 'terser'}, CSS with ${minifyConfig.css || 'cssnano'}, on ${parallel} CPU(s)`);
50
+ if (minifyConfig.minifier === 'esbuild') {
51
+ const { EsbuildPlugin } = require('esbuild-loader');
52
+ new EsbuildPlugin({
53
+ target: new browser_list_to_esbuild_target_factory_1.BrowserListToEsbuildTargetFactory().createTarget(),
54
+ drop: ['console'],
55
+ legalComments: 'none'
56
+ }).apply(compiler);
57
+ return;
58
+ }
59
+ const TerserPlugin = require('terser-webpack-plugin');
60
+ new TerserPlugin({
61
+ parallel,
62
+ extractComments: false,
63
+ terserOptions: {
64
+ output: {
65
+ comments: false
66
+ },
67
+ compress: {
68
+ drop_console: true,
69
+ passes: minifyConfig.passes || DEFAULT_TERSER_PASSES
70
+ },
71
+ sourceMap: true
72
+ }
73
+ }).apply(compiler);
74
+ }
75
+ ]
76
+ }
77
+ };
78
+ };
79
+ exports.ProductionConfig = ProductionConfig;
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const mode_1 = require("../enums/mode");
4
- const path = require('path');
5
- const process = require('process');
6
- const { RetryChunkLoadPlugin } = require(path.join(process.cwd(), 'node_modules', '@studyportals/webpack-helper', 'src', 'plugins', 'retry-chunk-load.plugin.js'));
4
+ const retry_chunk_load_plugin_1 = require("../plugins/retry-chunk-load.plugin");
7
5
  class ChunksRetryPluginFactory {
8
6
  static IsPresetSupported(preset) {
9
7
  if (!preset.retryChunksConfig)
@@ -19,13 +17,13 @@ class ChunksRetryPluginFactory {
19
17
  }
20
18
  static CustomRetryChunksPlugin(preset) {
21
19
  const { retryChunksConfig } = preset;
22
- return new RetryChunkLoadPlugin({
23
- cacheBust: `function() {
24
- return Date.now();
20
+ return new retry_chunk_load_plugin_1.RetryChunkLoadPlugin({
21
+ cacheBust: `function() {
22
+ return Date.now();
25
23
  }`,
26
- retryDelay: `function(retryAttempt) {
27
- return Math.min(2000, Math.pow(2, retryAttempt) * 100);
28
- }
24
+ retryDelay: `function(retryAttempt) {
25
+ return Math.min(2000, Math.pow(2, retryAttempt) * 100);
26
+ }
29
27
  `,
30
28
  maxRetries: retryChunksConfig.threshold,
31
29
  lastResortScript: ChunksRetryPluginFactory.CreateLastResortScript(preset)
@@ -35,18 +33,18 @@ class ChunksRetryPluginFactory {
35
33
  const { retryChunksConfig } = preset;
36
34
  let lastResortScript = ``;
37
35
  if (retryChunksConfig.thresholdReachedCallBack) {
38
- lastResortScript += `
39
- ${retryChunksConfig.thresholdReachedCallBack}
36
+ lastResortScript += `
37
+ ${retryChunksConfig.thresholdReachedCallBack}
40
38
  `;
41
39
  }
42
40
  if (!retryChunksConfig.disableDefaultRollbarError) {
43
41
  const rollbarInstanceIdentifier = retryChunksConfig.rollbarInstanceIdentifier || 'rollbar';
44
- lastResortScript += `
45
- if (!window || !window['${rollbarInstanceIdentifier}'] || !window['${rollbarInstanceIdentifier}'].error) {
46
- return;
47
- }
48
-
49
- window['${rollbarInstanceIdentifier}'].error(new Error('Failed to load chunk for after retries'));
42
+ lastResortScript += `
43
+ if (!window || !window['${rollbarInstanceIdentifier}'] || !window['${rollbarInstanceIdentifier}'].error) {
44
+ return;
45
+ }
46
+
47
+ window['${rollbarInstanceIdentifier}'].error(new Error('Failed to load chunk for after retries'));
50
48
  `;
51
49
  }
52
50
  return lastResortScript;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -23,6 +23,7 @@ const DEFAULT_CHUNKS_RETRY_CONFIG_THRESHOLD = 6;
23
23
  class Configuration {
24
24
  constructor(options) {
25
25
  this.customElementTags = options.customElementTags || [];
26
+ this.minifyConfig = options.minify || {};
26
27
  this.bob = options.bob || null;
27
28
  this.entry = new entry_1.Entry(options.entry);
28
29
  this.output = new output_1.Output(options.output);
@@ -36,7 +37,7 @@ class Configuration {
36
37
  const configPrd = options[mode_1.Mode.PRODUCTION] ? options[mode_1.Mode.PRODUCTION] : {};
37
38
  this.environmentSpecificConfig = {
38
39
  [mode_1.Mode.DEVELOPMENT]: merge([configDev, development_config_1.DevelopmentConfig]) || development_config_1.DevelopmentConfig,
39
- [mode_1.Mode.PRODUCTION]: merge([configPrd, (0, production_config_1.ProductionConfig)(this.bob)]) || (0, production_config_1.ProductionConfig)(this.bob)
40
+ [mode_1.Mode.PRODUCTION]: merge([configPrd, (0, production_config_1.ProductionConfig)(this.bob, this.minifyConfig)]) || (0, production_config_1.ProductionConfig)(this.bob, this.minifyConfig)
40
41
  };
41
42
  this.fileName = options.output.fileName || "[name]";
42
43
  this.chunksRetryConfig = options.chunksRetryConfig || {
@@ -17,8 +17,8 @@ class RetryChunkLoadPlugin {
17
17
  ? maxRetryValueFromOptions
18
18
  : 1;
19
19
  const getCacheBustString = () => this.options.cacheBust
20
- ? `
21
- (${this.options.cacheBust})();
20
+ ? `
21
+ (${this.options.cacheBust})();
22
22
  `
23
23
  : '"cache-bust=true"';
24
24
  mainTemplate.hooks.localVars.tap({ name: pluginName, stage: 1 }, (source, chunk) => {
@@ -30,41 +30,41 @@ class RetryChunkLoadPlugin {
30
30
  : `function() { return ${this.options.retryDelay || 0} }`;
31
31
  if (!addRetryCode)
32
32
  return source;
33
- const script = runtimeTemplate.iife('', `
34
- if(typeof ${RuntimeGlobals.require} !== "undefined") {
35
- var oldGetScript = ${RuntimeGlobals.getChunkScriptFilename};
36
- var oldLoadScript = ${RuntimeGlobals.ensureChunk};
37
- var queryMap = {};
38
- var countMap = {};
39
- var getRetryDelay = ${getRetryDelay}
40
- ${RuntimeGlobals.getChunkScriptFilename} = function(chunkId){
41
- var result = oldGetScript(chunkId);
42
- return result + (queryMap.hasOwnProperty(chunkId) ? '?' + queryMap[chunkId] : '');
43
- };
44
- ${RuntimeGlobals.ensureChunk} = function(chunkId){
45
- var result = oldLoadScript(chunkId);
46
- return result.catch(function(error){
47
- var retries = countMap.hasOwnProperty(chunkId) ? countMap[chunkId] : ${maxRetries};
48
- if (retries < 1) {
49
- var realSrc = oldGetScript(chunkId);
50
- error.message = 'Loading chunk ' + chunkId + ' failed after ${maxRetries} retries.\\n(' + realSrc + ')';
33
+ const script = runtimeTemplate.iife('', `
34
+ if(typeof ${RuntimeGlobals.require} !== "undefined") {
35
+ var oldGetScript = ${RuntimeGlobals.getChunkScriptFilename};
36
+ var oldLoadScript = ${RuntimeGlobals.ensureChunk};
37
+ var queryMap = {};
38
+ var countMap = {};
39
+ var getRetryDelay = ${getRetryDelay}
40
+ ${RuntimeGlobals.getChunkScriptFilename} = function(chunkId){
41
+ var result = oldGetScript(chunkId);
42
+ return result + (queryMap.hasOwnProperty(chunkId) ? '?' + queryMap[chunkId] : '');
43
+ };
44
+ ${RuntimeGlobals.ensureChunk} = function(chunkId){
45
+ var result = oldLoadScript(chunkId);
46
+ return result.catch(function(error){
47
+ var retries = countMap.hasOwnProperty(chunkId) ? countMap[chunkId] : ${maxRetries};
48
+ if (retries < 1) {
49
+ var realSrc = oldGetScript(chunkId);
50
+ error.message = 'Loading chunk ' + chunkId + ' failed after ${maxRetries} retries.\\n(' + realSrc + ')';
51
51
  error.request = realSrc;${this.options.lastResortScript
52
52
  ? this.options.lastResortScript
53
- : ''}
54
- throw error;
55
- }
56
- return new Promise(function (resolve) {
57
- var retryAttempt = ${maxRetries} - retries + 1;
58
- setTimeout(function () {
59
- var retryAttemptString = '&retry-attempt=' + retryAttempt;
60
- var cacheBust = ${getCacheBustString()} + retryAttemptString;
61
- queryMap[chunkId] = cacheBust;
62
- countMap[chunkId] = retries - 1;
63
- resolve(${RuntimeGlobals.ensureChunk}(chunkId));
64
- }, getRetryDelay(retryAttempt))
65
- })
66
- });
67
- };
53
+ : ''}
54
+ throw error;
55
+ }
56
+ return new Promise(function (resolve) {
57
+ var retryAttempt = ${maxRetries} - retries + 1;
58
+ setTimeout(function () {
59
+ var retryAttemptString = '&retry-attempt=' + retryAttempt;
60
+ var cacheBust = ${getCacheBustString()} + retryAttemptString;
61
+ queryMap[chunkId] = cacheBust;
62
+ countMap[chunkId] = retries - 1;
63
+ resolve(${RuntimeGlobals.ensureChunk}(chunkId));
64
+ }, getRetryDelay(retryAttempt))
65
+ })
66
+ });
67
+ };
68
68
  }`);
69
69
  return (source +
70
70
  prettier.format(script, {
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getAvailableCpus = void 0;
4
+ const os = require('os');
5
+ const fs = require('fs');
6
+ const getCgroupCpuLimit = () => {
7
+ try {
8
+ const [quota, period] = fs.readFileSync('/sys/fs/cgroup/cpu.max', 'utf8').trim().split(/\s+/);
9
+ return quota === 'max' ? null : Math.max(1, Math.floor(Number(quota) / Number(period)));
10
+ }
11
+ catch (e) { }
12
+ try {
13
+ const quota = Number(fs.readFileSync('/sys/fs/cgroup/cpu/cpu.cfs_quota_us', 'utf8'));
14
+ const period = Number(fs.readFileSync('/sys/fs/cgroup/cpu/cpu.cfs_period_us', 'utf8'));
15
+ return quota > 0 && period > 0 ? Math.max(1, Math.floor(quota / period)) : null;
16
+ }
17
+ catch (e) { }
18
+ return null;
19
+ };
20
+ const getAvailableCpus = () => {
21
+ const override = parseInt(process.env.WEBPACK_PARALLELISM || '', 10);
22
+ if (override > 0) {
23
+ return override;
24
+ }
25
+ const cpus = typeof os.availableParallelism === 'function' ? os.availableParallelism() : os.cpus().length;
26
+ const limit = getCgroupCpuLimit();
27
+ return Math.max(1, limit === null ? cpus : Math.min(cpus, limit));
28
+ };
29
+ exports.getAvailableCpus = getAvailableCpus;
package/package.json CHANGED
@@ -1,51 +1,55 @@
1
- {
2
- "name": "@studyportals/webpack-helper",
3
- "version": "8.1.0",
4
- "description": "A collection of standard configurations and helpers for webpack.",
5
- "main": "src/main.js",
6
- "scripts": {
7
- "test": "vitest --watch=false --coverage",
8
- "build": "tsc",
9
- "prepublish": "npm run build",
10
- "postinstall": "test -d ../../../ && cp ./assets/.browserslistrc ../../../ || true",
11
- "deploy-beta": "npm version prerelease && npm run build && npm publish --tag beta --access=public --auth-type=legacy && rm -rf node_modules"
12
- },
13
- "files": [
14
- "src/**/*.js",
15
- "assets/*"
16
- ],
17
- "author": {
18
- "name": "Frank Kluijtmans",
19
- "email": "frank@studyportals.com"
20
- },
21
- "license": "ISC",
22
- "dependencies": {
23
- "@studyportals/bob-manifest-generator": "^5.0.1",
24
- "@studyportals/browserslist-config": "^2.0.0",
25
- "@studyportals/dll-availability-tracker": "^2.0.0",
26
- "@studyportals/vue-config": "^5.0.3",
27
- "css-loader": "^6.10.0",
28
- "css-minimizer-webpack-plugin": "^6.0.0",
29
- "esbuild-loader": "^4.0.3",
30
- "esbuild-plugin-browserslist": "^0.11.1",
31
- "file-loader": "^6.2.0",
32
- "fork-ts-checker-webpack-plugin": "^9.0.2",
33
- "mini-css-extract-plugin": "^2.8.0",
34
- "path": "^0.12.7",
35
- "prettier": "^2.8.8",
36
- "sass": "^1.89.2",
37
- "sass-loader": "^16.0.5",
38
- "terser-webpack-plugin": "^5.3.10",
39
- "typescript": "^5.3.3",
40
- "vue-loader": "^17.4.2",
41
- "webpack": "^5.90.3",
42
- "webpack-cli": "^5.1.4",
43
- "webpack-dev-server": "^5.2.2",
44
- "webpack-merge": "^5.10.0"
45
- },
46
- "devDependencies": {
47
- "@types/node": "^20.11.20",
48
- "@vitest/coverage-v8": "^1.3.1",
49
- "vitest": "^1.3.1"
50
- }
51
- }
1
+ {
2
+ "name": "@studyportals/webpack-helper",
3
+ "version": "8.2.0-beta.0",
4
+ "description": "A collection of standard configurations and helpers for webpack.",
5
+ "main": "dist/main.js",
6
+ "scripts": {
7
+ "test": "vitest --watch=false --coverage",
8
+ "build": "rm -rf dist && tsc",
9
+ "prepublishOnly": "npm run build",
10
+ "postinstall": "test -d ../../../ && cp ./assets/.browserslistrc ../../../ || true",
11
+ "version:alpha": "sh ./scripts/version.sh alpha",
12
+ "version:beta": "sh ./scripts/version.sh beta",
13
+ "version:latest": "sh ./scripts/version.sh latest",
14
+ "release": "sh ./scripts/release.sh"
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "assets/*"
19
+ ],
20
+ "author": {
21
+ "name": "Frank Kluijtmans",
22
+ "email": "frank@studyportals.com"
23
+ },
24
+ "license": "ISC",
25
+ "dependencies": {
26
+ "@studyportals/bob-manifest-generator": "^5.0.1",
27
+ "@studyportals/browserslist-config": "^2.0.0",
28
+ "@studyportals/dll-availability-tracker": "^2.0.0",
29
+ "@studyportals/vue-config": "^5.0.3",
30
+ "css-loader": "^6.10.0",
31
+ "css-minimizer-webpack-plugin": "^6.0.0",
32
+ "esbuild-loader": "^4.0.3",
33
+ "esbuild-plugin-browserslist": "^0.11.1",
34
+ "file-loader": "^6.2.0",
35
+ "fork-ts-checker-webpack-plugin": "^9.0.2",
36
+ "lightningcss": "^1.33.0",
37
+ "mini-css-extract-plugin": "^2.8.0",
38
+ "path": "^0.12.7",
39
+ "prettier": "^2.8.8",
40
+ "sass": "^1.89.2",
41
+ "sass-loader": "^16.0.5",
42
+ "terser-webpack-plugin": "^5.3.10",
43
+ "typescript": "^5.3.3",
44
+ "vue-loader": "^17.4.2",
45
+ "webpack": "^5.90.3",
46
+ "webpack-cli": "^5.1.4",
47
+ "webpack-dev-server": "^5.2.2",
48
+ "webpack-merge": "^5.10.0"
49
+ },
50
+ "devDependencies": {
51
+ "@types/node": "^20.11.20",
52
+ "@vitest/coverage-v8": "^1.3.1",
53
+ "vitest": "^1.3.1"
54
+ }
55
+ }
@@ -1,59 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ProductionConfig = void 0;
4
- const webpack = require('webpack');
5
- const cssMinimizerPlugin = require('css-minimizer-webpack-plugin');
6
- const DllAvailabilityTracker = require('@studyportals/dll-availability-tracker');
7
- const ProductionConfig = (bobConfig) => {
8
- let dllDependencies = ['library'];
9
- if (bobConfig && bobConfig.hasOwnProperty('dllPackages')) {
10
- bobConfig.dllPackages.forEach((dependency) => dllDependencies.push(dependency.manifest.name));
11
- }
12
- return {
13
- plugins: [
14
- new webpack.DefinePlugin({
15
- 'process.env': {
16
- NODE_ENV: '"production"'
17
- }
18
- }),
19
- new cssMinimizerPlugin({
20
- minimizerOptions: {
21
- preset: [
22
- 'default',
23
- {
24
- discardComments: {
25
- removeAll: true
26
- }
27
- }
28
- ]
29
- },
30
- }),
31
- new DllAvailabilityTracker({
32
- dependencies: dllDependencies || []
33
- })
34
- ],
35
- optimization: {
36
- minimize: true,
37
- minimizer: [
38
- compiler => {
39
- const TerserPlugin = require('terser-webpack-plugin');
40
- new TerserPlugin({
41
- parallel: true,
42
- extractComments: false,
43
- terserOptions: {
44
- output: {
45
- comments: false
46
- },
47
- compress: {
48
- drop_console: true,
49
- passes: 5
50
- },
51
- sourceMap: true
52
- }
53
- }).apply(compiler);
54
- }
55
- ]
56
- }
57
- };
58
- };
59
- exports.ProductionConfig = ProductionConfig;
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes