@nitro/webpack 10.0.3 → 11.0.0-beta.1
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/lib/utils.js +12 -9
- package/lib/webpack-rules.js +124 -0
- package/package.json +29 -27
- package/readme.md +20 -37
- package/webpack-config/webpack.config.dev.js +50 -66
- package/webpack-config/webpack.config.prod.js +311 -318
- package/plugins/dynamicAliasResolver.js +0 -31
package/lib/utils.js
CHANGED
|
@@ -16,15 +16,18 @@ function getEnrichedConfig(rule, config) {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
// load optional package
|
|
19
|
-
function getOptionalPackage(x) {
|
|
20
|
-
let mod;
|
|
21
|
-
try {
|
|
22
|
-
mod = require(x);
|
|
23
|
-
} catch (error) {
|
|
24
|
-
mod = null;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
19
|
+
function getOptionalPackage(x) {
|
|
20
|
+
let mod;
|
|
21
|
+
try {
|
|
22
|
+
mod = require(x);
|
|
23
|
+
} catch (error) {
|
|
24
|
+
mod = null;
|
|
25
|
+
}
|
|
26
|
+
if (!mod) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
return mod.default ? mod.default : mod;
|
|
30
|
+
}
|
|
28
31
|
|
|
29
32
|
module.exports = {
|
|
30
33
|
getEnrichedConfig,
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const typescript = require('typescript');
|
|
6
|
+
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
|
7
|
+
const utils = require('./utils');
|
|
8
|
+
|
|
9
|
+
function resolveBabelConfigFile(context, ruleOptions) {
|
|
10
|
+
if (ruleOptions && ruleOptions.babelConfigFile) {
|
|
11
|
+
return path.resolve(context, ruleOptions.babelConfigFile);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const candidates = ['babel.config.js', '.babelrc', '.babelrc.js', '.babelrc.json'];
|
|
15
|
+
for (const candidate of candidates) {
|
|
16
|
+
const candidatePath = path.resolve(context, candidate);
|
|
17
|
+
if (fs.existsSync(candidatePath)) {
|
|
18
|
+
return candidatePath;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function resolveTsConfigFile(context, ruleOptions) {
|
|
26
|
+
if (ruleOptions && ruleOptions.tsConfigFile) {
|
|
27
|
+
return path.resolve(context, ruleOptions.tsConfigFile);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return typescript.findConfigFile(context, fs.existsSync);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function getRuleOptions(ruleOptions) {
|
|
34
|
+
return ruleOptions && typeof ruleOptions === 'object' ? ruleOptions : null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function ensureResolveExtensions(webpackConfig, extensions, { prepend }) {
|
|
38
|
+
if (!webpackConfig.resolve) {
|
|
39
|
+
webpackConfig.resolve = {};
|
|
40
|
+
}
|
|
41
|
+
if (!Array.isArray(webpackConfig.resolve.extensions)) {
|
|
42
|
+
webpackConfig.resolve.extensions = ['.js', '.json'];
|
|
43
|
+
}
|
|
44
|
+
const target = webpackConfig.resolve.extensions;
|
|
45
|
+
const missing = extensions.filter((ext) => !target.includes(ext));
|
|
46
|
+
if (missing.length === 0) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (prepend) {
|
|
50
|
+
target.unshift(...missing);
|
|
51
|
+
} else {
|
|
52
|
+
target.push(...missing);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function getBabelLoaderOptions(context, ruleOptions) {
|
|
57
|
+
const babelConfigFile = resolveBabelConfigFile(context, ruleOptions);
|
|
58
|
+
const babelLoaderOptions = {
|
|
59
|
+
cacheDirectory: true,
|
|
60
|
+
compact: true,
|
|
61
|
+
};
|
|
62
|
+
if (babelConfigFile) {
|
|
63
|
+
babelLoaderOptions.configFile = babelConfigFile;
|
|
64
|
+
}
|
|
65
|
+
return babelLoaderOptions;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function addJSConfig(webpackConfig, context, ruleOptions) {
|
|
69
|
+
const babelLoaderOptions = getBabelLoaderOptions(context, ruleOptions);
|
|
70
|
+
const scriptRuleJs = {
|
|
71
|
+
test: /\.[cm]?jsx?$/,
|
|
72
|
+
exclude: [/[/\\\\]node_modules[/\\\\]/],
|
|
73
|
+
use: [
|
|
74
|
+
{
|
|
75
|
+
loader: require.resolve('babel-loader'),
|
|
76
|
+
options: babelLoaderOptions,
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
};
|
|
80
|
+
webpackConfig.module.rules.push(utils.getEnrichedConfig(scriptRuleJs, getRuleOptions(ruleOptions)));
|
|
81
|
+
ensureResolveExtensions(webpackConfig, ['.js', '.jsx', '.mjs', '.cjs'], { prepend: true });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function addTsConfig(webpackConfig, context, ruleOptions, { isProduction }) {
|
|
85
|
+
const babelLoaderOptions = getBabelLoaderOptions(context, ruleOptions);
|
|
86
|
+
const scriptRuleTs = {
|
|
87
|
+
test: /\.[cm]?tsx?$/,
|
|
88
|
+
exclude: [/[/\\\\]node_modules[/\\\\]/],
|
|
89
|
+
use: [
|
|
90
|
+
{
|
|
91
|
+
loader: require.resolve('babel-loader'),
|
|
92
|
+
options: babelLoaderOptions,
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
loader: require.resolve('ts-loader'),
|
|
96
|
+
options: {
|
|
97
|
+
transpileOnly: true,
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
};
|
|
102
|
+
webpackConfig.module.rules.push(utils.getEnrichedConfig(scriptRuleTs, getRuleOptions(ruleOptions)));
|
|
103
|
+
ensureResolveExtensions(webpackConfig, ['.ts', '.tsx', '.mts', '.cts'], { prepend: true });
|
|
104
|
+
|
|
105
|
+
const tsConfigFile = resolveTsConfigFile(context, ruleOptions);
|
|
106
|
+
if (tsConfigFile) {
|
|
107
|
+
const forkCheckerOptions = {
|
|
108
|
+
async: !isProduction,
|
|
109
|
+
typescript: {
|
|
110
|
+
diagnosticOptions: {
|
|
111
|
+
semantic: true,
|
|
112
|
+
syntactic: true,
|
|
113
|
+
},
|
|
114
|
+
configFile: tsConfigFile,
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
webpackConfig.plugins.push(new ForkTsCheckerWebpackPlugin(forkCheckerOptions));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
module.exports = {
|
|
122
|
+
addJSConfig,
|
|
123
|
+
addTsConfig,
|
|
124
|
+
};
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nitro/webpack",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "11.0.0-beta.1",
|
|
4
4
|
"description": "nitro webpack",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "The Nitro Team",
|
|
7
7
|
"engines": {
|
|
8
|
-
"node": ">=
|
|
9
|
-
"npm": ">=10.
|
|
8
|
+
"node": ">=22.11.0 <25",
|
|
9
|
+
"npm": ">=10.9.0 <12"
|
|
10
10
|
},
|
|
11
11
|
"scripts": {
|
|
12
12
|
"lint": "eslint .",
|
|
@@ -15,52 +15,54 @@
|
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
17
|
"lib",
|
|
18
|
-
"plugins",
|
|
19
18
|
"webpack-config"
|
|
20
19
|
],
|
|
21
20
|
"keywords": [
|
|
22
21
|
"frontend",
|
|
23
22
|
"nitro"
|
|
24
23
|
],
|
|
24
|
+
"peerDependencies": {
|
|
25
|
+
"@nitro/app": ">=11.0.0-beta.1",
|
|
26
|
+
"webpack": "^5"
|
|
27
|
+
},
|
|
25
28
|
"dependencies": {
|
|
26
|
-
"@babel/core": "7.
|
|
27
|
-
"@babel/preset-env": "7.
|
|
29
|
+
"@babel/core": "7.29.0",
|
|
30
|
+
"@babel/preset-env": "7.29.0",
|
|
28
31
|
"@babel/preset-react": "7.28.5",
|
|
29
|
-
"@babel/plugin-proposal-decorators": "7.
|
|
30
|
-
"@babel/plugin-transform-class-properties": "7.
|
|
31
|
-
"autoprefixer": "10.4.
|
|
32
|
+
"@babel/plugin-proposal-decorators": "7.29.0",
|
|
33
|
+
"@babel/plugin-transform-class-properties": "7.28.6",
|
|
34
|
+
"autoprefixer": "10.4.24",
|
|
35
|
+
"babel-loader": "10.0.0",
|
|
32
36
|
"case-sensitive-paths-webpack-plugin": "2.4.0",
|
|
33
|
-
"css-loader": "
|
|
37
|
+
"css-loader": "7.1.3",
|
|
34
38
|
"cssnano": "7.1.2",
|
|
35
|
-
"
|
|
39
|
+
"image-minimizer-webpack-plugin": "4.1.4",
|
|
40
|
+
"fork-ts-checker-webpack-plugin": "9.1.0",
|
|
36
41
|
"handlebars-loader": "1.7.3",
|
|
37
|
-
"imagemin": "
|
|
38
|
-
"
|
|
39
|
-
"js-config-webpack-plugin": "2.0.3",
|
|
40
|
-
"mini-css-extract-plugin": "1.6.2",
|
|
42
|
+
"imagemin": "9.0.1",
|
|
43
|
+
"mini-css-extract-plugin": "2.10.0",
|
|
41
44
|
"postcss": "8.5.6",
|
|
42
|
-
"postcss-loader": "
|
|
45
|
+
"postcss-loader": "8.2.0",
|
|
43
46
|
"resolve-url-loader": "5.0.0",
|
|
44
|
-
"sass": "1.
|
|
45
|
-
"sass-loader": "
|
|
46
|
-
"
|
|
47
|
-
"ts-
|
|
47
|
+
"sass": "1.97.3",
|
|
48
|
+
"sass-loader": "16.0.7",
|
|
49
|
+
"thread-loader": "4.0.4",
|
|
50
|
+
"ts-loader": "9.5.4",
|
|
48
51
|
"typescript": "5.9.3",
|
|
49
|
-
"url-loader": "4.1.1",
|
|
50
|
-
"webpack": "4.47.0",
|
|
51
52
|
"webpackbar": "7.0.0",
|
|
52
|
-
"webpack-bundle-analyzer": "
|
|
53
|
+
"webpack-bundle-analyzer": "5.2.0"
|
|
53
54
|
},
|
|
54
55
|
"optionalDependencies": {
|
|
55
|
-
"imagemin-mozjpeg": "
|
|
56
|
+
"imagemin-mozjpeg": "10.0.0",
|
|
56
57
|
"imagemin-optipng": "8.0.0",
|
|
57
|
-
"imagemin-pngquant": "
|
|
58
|
-
"imagemin-svgo": "
|
|
58
|
+
"imagemin-pngquant": "10.0.0",
|
|
59
|
+
"imagemin-svgo": "11.0.1"
|
|
59
60
|
},
|
|
60
61
|
"devDependencies": {
|
|
61
62
|
"@merkle-open/eslint-config": "4.0.1",
|
|
62
63
|
"eslint": "8.57.1",
|
|
63
|
-
"eslint-plugin-import": "2.32.0"
|
|
64
|
+
"eslint-plugin-import": "2.32.0",
|
|
65
|
+
"webpack": "5.105.2"
|
|
64
66
|
},
|
|
65
67
|
"publishConfig": {
|
|
66
68
|
"access": "public"
|
package/readme.md
CHANGED
|
@@ -4,16 +4,15 @@
|
|
|
4
4
|
|
|
5
5
|
# Nitro Webpack
|
|
6
6
|
|
|
7
|
-
Configurable and easy to use webpack
|
|
7
|
+
Configurable and easy to use webpack 5 config for nitro projects.
|
|
8
8
|
|
|
9
9
|
## Usage
|
|
10
10
|
|
|
11
11
|
```
|
|
12
12
|
const options = {
|
|
13
13
|
rules: {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
scss: true,
|
|
14
|
+
script: true,
|
|
15
|
+
style: true,
|
|
17
16
|
hbs: true,
|
|
18
17
|
woff: true,
|
|
19
18
|
font: false,
|
|
@@ -22,8 +21,8 @@ const options = {
|
|
|
22
21
|
features: {
|
|
23
22
|
banner: true,
|
|
24
23
|
bundleAnalyzer: false,
|
|
24
|
+
imageMinimizer: true,
|
|
25
25
|
theme: false,
|
|
26
|
-
dynamicAlias: false,
|
|
27
26
|
},
|
|
28
27
|
};
|
|
29
28
|
const webpackConfig = require('@nitro/webpack/webpack-config/webpack.config.dev')(options);
|
|
@@ -37,27 +36,20 @@ module.exports = webpackConfig;
|
|
|
37
36
|
|
|
38
37
|
No loader rule is enabled by default. Activate following prepared rules you need in `options.rules`
|
|
39
38
|
|
|
40
|
-
#### `options.rules.
|
|
39
|
+
#### `options.rules.script`
|
|
41
40
|
|
|
42
41
|
- Type: boolean || object
|
|
43
42
|
- default: false
|
|
44
|
-
- file types: js, jsx, mjs
|
|
43
|
+
- file types: js, jsx, mjs, cjs (and optional ts, tsx, mts, cts)
|
|
45
44
|
|
|
46
45
|
Config:
|
|
47
46
|
|
|
48
|
-
- `true` or `{}` activates JavaScript support
|
|
47
|
+
- `true` or `{}` activates JavaScript support (via Babel)
|
|
48
|
+
- `{ typescript: true }` adds TypeScript support
|
|
49
|
+
- `{ babelConfigFile: 'path/to/babel.config.js' }` will be used as Babel config (default: auto-detect)
|
|
50
|
+
- `{ tsConfigFile: 'path/to/tsconfig.json' }` is used for type-checking with ForkTsCheckerWebpackPlugin (default: auto-detect)
|
|
49
51
|
|
|
50
|
-
#### `options.rules.
|
|
51
|
-
|
|
52
|
-
- Type: boolean
|
|
53
|
-
- default: false
|
|
54
|
-
- file types: ts, tsx
|
|
55
|
-
|
|
56
|
-
Config:
|
|
57
|
-
|
|
58
|
-
- `true` will activate TypeScript support
|
|
59
|
-
|
|
60
|
-
#### `options.rules.scss`
|
|
52
|
+
#### `options.rules.style`
|
|
61
53
|
|
|
62
54
|
- Type: boolean || object
|
|
63
55
|
- default: false
|
|
@@ -65,10 +57,9 @@ Config:
|
|
|
65
57
|
|
|
66
58
|
Config:
|
|
67
59
|
|
|
68
|
-
- `true` or `{}` will activate scss support
|
|
60
|
+
- `true` or `{}` will activate css & scss support
|
|
69
61
|
- `{ publicPath: '../' }` provide a separate public path for stylesheets. By default, webpack uses the value from 'output.publicPath'. (only relevant for production build)
|
|
70
|
-
- `{
|
|
71
|
-
- `{ sassOptions: { ... } }` gives the possibility to add options for the ['dart-sass'](https://sass-lang.com/documentation/js-api/interfaces/options/) or ['node-sass'](https://github.com/sass/node-sass/#options) implementation (e.g. ignore some deprecations for dart-sass with `silenceDeprecations: [...]`)
|
|
62
|
+
- `{ sassOptions: { ... } }` gives the possibility to add options for the ['dart-sass'](https://sass-lang.com/documentation/js-api/interfaces/options/)
|
|
72
63
|
|
|
73
64
|
#### `options.rules.hbs`
|
|
74
65
|
|
|
@@ -141,6 +132,13 @@ Enable some additional features
|
|
|
141
132
|
|
|
142
133
|
`true` will add the bundleAnalyser plugin and opens a browser window with the stats
|
|
143
134
|
|
|
135
|
+
#### `options.features.imageMinimizer`
|
|
136
|
+
|
|
137
|
+
- Type: boolean
|
|
138
|
+
- default: true
|
|
139
|
+
|
|
140
|
+
`false` will disable image minifaction functionality
|
|
141
|
+
|
|
144
142
|
#### `options.features.theme`
|
|
145
143
|
|
|
146
144
|
- Type: string || false
|
|
@@ -153,21 +151,6 @@ A string will activate theming support:
|
|
|
153
151
|
|
|
154
152
|
It makes sense to use a dynamic value e.g. an environment variable, as shown in the example configuration.
|
|
155
153
|
|
|
156
|
-
#### `options.features.dynamicAlias`
|
|
157
|
-
|
|
158
|
-
- Type: object || false
|
|
159
|
-
- default: false
|
|
160
|
-
|
|
161
|
-
A proper configured dynamicAlias feature will activate the DynamicAliasResolverPlugin
|
|
162
|
-
which can change import paths in source files dynamically on compile time as desired.
|
|
163
|
-
|
|
164
|
-
Properties:
|
|
165
|
-
|
|
166
|
-
- `options.features.dynamicAlias.search` (string || RegExp)
|
|
167
|
-
search term to be replaced (e.g. '/theme/light')
|
|
168
|
-
- `options.features.dynamicAlias.replace` (string)
|
|
169
|
-
string as replacement (e.g. `/theme/${theme}`)
|
|
170
|
-
|
|
171
154
|
## Extending Configuration
|
|
172
155
|
|
|
173
156
|
### Code Splitting
|
|
@@ -1,26 +1,19 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const fs = require('fs');
|
|
3
|
-
const crypto = require('crypto');
|
|
4
3
|
const webpack = require('webpack');
|
|
5
4
|
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
|
|
6
5
|
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
|
|
7
|
-
const JsConfigWebpackPlugin = require('js-config-webpack-plugin');
|
|
8
6
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
9
|
-
const TsConfigWebpackPlugin = require('ts-config-webpack-plugin');
|
|
10
|
-
const DynamicAliasResolverPlugin = require('../plugins/dynamicAliasResolver');
|
|
11
7
|
const utils = require('../lib/utils');
|
|
8
|
+
const webpackRules = require('../lib/webpack-rules');
|
|
12
9
|
|
|
13
10
|
const hotMiddlewareScript = 'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000&reload=true';
|
|
14
11
|
const appDirectory = fs.realpathSync(process.cwd());
|
|
15
12
|
|
|
16
|
-
// hack: OpenSSL 3 does not support md4 anymore, but legacy webpack 4 hardcoded it: https://github.com/webpack/webpack/issues/13572
|
|
17
|
-
const crypto_orig_createHash = crypto.createHash;
|
|
18
|
-
crypto.createHash = algorithm => crypto_orig_createHash(algorithm === 'md4' ? 'sha256' : algorithm);
|
|
19
|
-
|
|
20
13
|
module.exports = (options = { rules: {}, features: {} }) => {
|
|
21
14
|
const webpackConfig = {
|
|
22
15
|
mode: 'development',
|
|
23
|
-
devtool: '
|
|
16
|
+
devtool: 'source-map',
|
|
24
17
|
context: appDirectory,
|
|
25
18
|
entry: {
|
|
26
19
|
ui: ['./src/ui', hotMiddlewareScript],
|
|
@@ -29,7 +22,7 @@ module.exports = (options = { rules: {}, features: {} }) => {
|
|
|
29
22
|
output: {
|
|
30
23
|
path: path.resolve(appDirectory, 'public', 'assets'),
|
|
31
24
|
filename: 'js/[name].js',
|
|
32
|
-
chunkFilename: 'js/[name]-[
|
|
25
|
+
chunkFilename: 'js/[name]-[contenthash:7].js',
|
|
33
26
|
publicPath: '/assets/',
|
|
34
27
|
pathinfo: false,
|
|
35
28
|
},
|
|
@@ -52,47 +45,43 @@ module.exports = (options = { rules: {}, features: {} }) => {
|
|
|
52
45
|
],
|
|
53
46
|
},
|
|
54
47
|
optimization: {
|
|
55
|
-
|
|
48
|
+
emitOnErrors: false,
|
|
49
|
+
moduleIds: 'deterministic',
|
|
50
|
+
chunkIds: 'deterministic',
|
|
51
|
+
runtimeChunk: 'single',
|
|
56
52
|
splitChunks: {
|
|
57
|
-
|
|
58
|
-
|
|
53
|
+
chunks: 'all',
|
|
54
|
+
minSize: 3000,
|
|
59
55
|
cacheGroups: {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
minSize: 3000,
|
|
63
|
-
chunks: 'async',
|
|
64
|
-
priority: 0,
|
|
65
|
-
},
|
|
66
|
-
// extract js node_modules to vendors file
|
|
56
|
+
default: false,
|
|
57
|
+
defaultVendors: false,
|
|
67
58
|
vendors: {
|
|
68
59
|
test: /[\\/]node_modules[\\/].*\.(js|jsx|mjs|ts|tsx)$/,
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
// Exclude proto dependencies going into vendors
|
|
72
|
-
chunks: (chunk) => chunk.name !== 'proto',
|
|
73
|
-
priority: -10,
|
|
60
|
+
chunks: (chunk) => chunk.canBeInitial() && chunk.name && chunk.name !== 'proto',
|
|
61
|
+
name: 'vendors',
|
|
74
62
|
enforce: true,
|
|
75
63
|
},
|
|
76
64
|
},
|
|
77
65
|
},
|
|
78
66
|
},
|
|
79
67
|
stats: {
|
|
80
|
-
|
|
68
|
+
preset: 'errors-warnings',
|
|
81
69
|
assets: false,
|
|
82
70
|
children: false,
|
|
83
71
|
chunks: false,
|
|
84
72
|
modules: false,
|
|
85
73
|
colors: true,
|
|
86
|
-
depth: false,
|
|
87
74
|
entrypoints: false,
|
|
88
75
|
errors: true,
|
|
89
76
|
errorDetails: false,
|
|
90
77
|
hash: false,
|
|
78
|
+
builtAt: false,
|
|
79
|
+
timings: false,
|
|
91
80
|
performance: true,
|
|
92
81
|
warnings: true,
|
|
93
82
|
},
|
|
94
83
|
infrastructureLogging: {
|
|
95
|
-
level: 'warn'
|
|
84
|
+
level: 'warn',
|
|
96
85
|
}
|
|
97
86
|
};
|
|
98
87
|
const theme = options.features.theme ? options.features.theme : false;
|
|
@@ -103,21 +92,20 @@ module.exports = (options = { rules: {}, features: {} }) => {
|
|
|
103
92
|
webpackConfig.output.publicPath = `${webpackConfig.output.publicPath}${theme}/`;
|
|
104
93
|
}
|
|
105
94
|
|
|
106
|
-
// js
|
|
107
|
-
if (options.rules.
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
webpackConfig.plugins.push(new TsConfigWebpackPlugin());
|
|
95
|
+
// scripts (js/ts via babel)
|
|
96
|
+
if (options.rules.script) {
|
|
97
|
+
const scriptOptions = typeof options.rules.script === 'object' ? options.rules.script : null;
|
|
98
|
+
webpackRules.addJSConfig(webpackConfig, appDirectory, scriptOptions);
|
|
99
|
+
if (scriptOptions && scriptOptions.typescript) {
|
|
100
|
+
webpackRules.addTsConfig(webpackConfig, appDirectory, scriptOptions, { isProduction: false });
|
|
101
|
+
}
|
|
114
102
|
}
|
|
115
103
|
|
|
116
104
|
// css & scss
|
|
117
|
-
if (options.rules.
|
|
105
|
+
if (options.rules.style) {
|
|
118
106
|
const scssLoaderOptions = {
|
|
119
|
-
|
|
120
|
-
...(options.rules.
|
|
107
|
+
sourceMap: true,
|
|
108
|
+
...(options.rules.style.sassOptions && { sassOptions: options.rules.style.sassOptions }),
|
|
121
109
|
};
|
|
122
110
|
webpackConfig.module.rules.push({
|
|
123
111
|
test: /\.s?css$/,
|
|
@@ -129,11 +117,13 @@ module.exports = (options = { rules: {}, features: {} }) => {
|
|
|
129
117
|
loader: require.resolve('css-loader'),
|
|
130
118
|
options: {
|
|
131
119
|
importLoaders: 2,
|
|
120
|
+
sourceMap: true,
|
|
132
121
|
},
|
|
133
122
|
},
|
|
134
123
|
{
|
|
135
124
|
loader: require.resolve('postcss-loader'),
|
|
136
125
|
options: {
|
|
126
|
+
sourceMap: true,
|
|
137
127
|
postcssOptions: () => {
|
|
138
128
|
return {
|
|
139
129
|
plugins: [
|
|
@@ -151,6 +141,9 @@ module.exports = (options = { rules: {}, features: {} }) => {
|
|
|
151
141
|
},
|
|
152
142
|
{
|
|
153
143
|
loader: require.resolve('resolve-url-loader'),
|
|
144
|
+
options: {
|
|
145
|
+
sourceMap: true,
|
|
146
|
+
},
|
|
154
147
|
},
|
|
155
148
|
{
|
|
156
149
|
loader: require.resolve('sass-loader'),
|
|
@@ -163,12 +156,6 @@ module.exports = (options = { rules: {}, features: {} }) => {
|
|
|
163
156
|
new MiniCssExtractPlugin({
|
|
164
157
|
filename: 'css/[name].css',
|
|
165
158
|
}),
|
|
166
|
-
// we need SourceMapDevToolPlugin to make sourcemaps work
|
|
167
|
-
// with MiniCSSExtractPlugin hmr mode
|
|
168
|
-
// related: https://github.com/webpack-contrib/mini-css-extract-plugin/issues/29
|
|
169
|
-
new webpack.SourceMapDevToolPlugin({
|
|
170
|
-
filename: '[file].map',
|
|
171
|
-
})
|
|
172
159
|
);
|
|
173
160
|
}
|
|
174
161
|
|
|
@@ -195,11 +182,9 @@ module.exports = (options = { rules: {}, features: {} }) => {
|
|
|
195
182
|
if (options.rules.woff) {
|
|
196
183
|
const woffRule = {
|
|
197
184
|
test: /.(woff(2)?)(\?[a-z0-9]+)?$/,
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
name: 'media/fonts/[name]-[hash:7].[ext]',
|
|
202
|
-
},
|
|
185
|
+
type: 'asset/resource',
|
|
186
|
+
generator: {
|
|
187
|
+
filename: 'media/fonts/[name]-[contenthash:7].[ext]',
|
|
203
188
|
},
|
|
204
189
|
};
|
|
205
190
|
webpackConfig.module.rules.push(utils.getEnrichedConfig(woffRule, options.rules.woff));
|
|
@@ -209,13 +194,15 @@ module.exports = (options = { rules: {}, features: {} }) => {
|
|
|
209
194
|
if (options.rules.font) {
|
|
210
195
|
const fontRule = {
|
|
211
196
|
test: /\.(eot|svg|ttf|woff|woff2)([?#]+[A-Za-z0-9-_]*)*$/,
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
name: 'media/font/[name]-[hash:7].[ext]',
|
|
197
|
+
type: 'asset',
|
|
198
|
+
parser: {
|
|
199
|
+
dataUrlCondition: {
|
|
200
|
+
maxSize: 2 * 1028,
|
|
217
201
|
},
|
|
218
202
|
},
|
|
203
|
+
generator: {
|
|
204
|
+
filename: 'media/font/[name]-[contenthash:7].[ext]',
|
|
205
|
+
},
|
|
219
206
|
};
|
|
220
207
|
webpackConfig.module.rules.push(utils.getEnrichedConfig(fontRule, options.rules.font));
|
|
221
208
|
}
|
|
@@ -224,8 +211,14 @@ module.exports = (options = { rules: {}, features: {} }) => {
|
|
|
224
211
|
if (options.rules.image) {
|
|
225
212
|
const imageRule = {
|
|
226
213
|
test: /\.(png|jpg|gif|svg)$/,
|
|
227
|
-
|
|
228
|
-
|
|
214
|
+
type: 'asset',
|
|
215
|
+
parser: {
|
|
216
|
+
dataUrlCondition: {
|
|
217
|
+
maxSize: 3 * 1028,
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
generator: {
|
|
221
|
+
filename: 'media/[ext]/[name]-[contenthash:7].[ext]',
|
|
229
222
|
},
|
|
230
223
|
};
|
|
231
224
|
webpackConfig.module.rules.push(utils.getEnrichedConfig(imageRule, options.rules.image));
|
|
@@ -236,15 +229,6 @@ module.exports = (options = { rules: {}, features: {} }) => {
|
|
|
236
229
|
webpackConfig.plugins.push(new BundleAnalyzerPlugin());
|
|
237
230
|
}
|
|
238
231
|
|
|
239
|
-
// feature dynamic alias
|
|
240
|
-
if (
|
|
241
|
-
options.features.dynamicAlias &&
|
|
242
|
-
options.features.dynamicAlias.search &&
|
|
243
|
-
options.features.dynamicAlias.replace
|
|
244
|
-
) {
|
|
245
|
-
webpackConfig.resolve.plugins = [new DynamicAliasResolverPlugin(options.features.dynamicAlias)];
|
|
246
|
-
}
|
|
247
|
-
|
|
248
232
|
return webpackConfig;
|
|
249
233
|
};
|
|
250
234
|
module.exports.hotMiddlewareScript = hotMiddlewareScript;
|
|
@@ -1,318 +1,311 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const fs = require('fs');
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
)
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
const imageRule = {
|
|
284
|
-
test: /\.(png|jpg|gif|svg)$/,
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
) {
|
|
313
|
-
webpackConfig.resolve.plugins = [new DynamicAliasResolverPlugin(options.features.dynamicAlias)];
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
return webpackConfig;
|
|
317
|
-
};
|
|
318
|
-
module.exports.appDirectory = appDirectory;
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const webpack = require('webpack');
|
|
4
|
+
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
|
|
5
|
+
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
|
|
6
|
+
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
7
|
+
const TerserPlugin = require('terser-webpack-plugin');
|
|
8
|
+
const WebpackBar = require('webpackbar');
|
|
9
|
+
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
|
|
10
|
+
const utils = require('../lib/utils');
|
|
11
|
+
const webpackRules = require('../lib/webpack-rules');
|
|
12
|
+
|
|
13
|
+
const appDirectory = fs.realpathSync(process.cwd());
|
|
14
|
+
|
|
15
|
+
const bannerData = {
|
|
16
|
+
date: new Date().toISOString().slice(0, 19),
|
|
17
|
+
pkg: require(`${appDirectory}/package.json`),
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const banner = `${bannerData.pkg.name}
|
|
21
|
+
@version v${bannerData.pkg.version}
|
|
22
|
+
@date ${bannerData.date}`;
|
|
23
|
+
|
|
24
|
+
module.exports = (options = { rules: {}, features: {} }) => {
|
|
25
|
+
const imageMinimizerPlugins = [];
|
|
26
|
+
const imageminMozjpeg = utils.getOptionalPackage('imagemin-mozjpeg');
|
|
27
|
+
const imageminOptipng = utils.getOptionalPackage('imagemin-optipng');
|
|
28
|
+
const imageminPngquant = utils.getOptionalPackage('imagemin-pngquant');
|
|
29
|
+
const imageminSvgo = utils.getOptionalPackage('imagemin-svgo');
|
|
30
|
+
|
|
31
|
+
if (imageminMozjpeg) {
|
|
32
|
+
imageMinimizerPlugins.push(
|
|
33
|
+
[
|
|
34
|
+
'mozjpeg',
|
|
35
|
+
{
|
|
36
|
+
quality: 75,
|
|
37
|
+
progressive: true,
|
|
38
|
+
},
|
|
39
|
+
]
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
if (imageminOptipng) {
|
|
43
|
+
imageMinimizerPlugins.push(
|
|
44
|
+
[
|
|
45
|
+
'optipng',
|
|
46
|
+
{
|
|
47
|
+
optimizationLevel: 7,
|
|
48
|
+
},
|
|
49
|
+
]
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
if (imageminPngquant) {
|
|
53
|
+
imageMinimizerPlugins.push('pngquant');
|
|
54
|
+
}
|
|
55
|
+
if (imageminSvgo) {
|
|
56
|
+
imageMinimizerPlugins.push(
|
|
57
|
+
[
|
|
58
|
+
'svgo',
|
|
59
|
+
{
|
|
60
|
+
plugins: [
|
|
61
|
+
{
|
|
62
|
+
name: 'preset-default',
|
|
63
|
+
params: {
|
|
64
|
+
overrides: {
|
|
65
|
+
removeViewBox: false,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
]
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const minimizerPlugins = [new TerserPlugin({ extractComments: false })];
|
|
76
|
+
if (!(options.features.imageMinimizer === false || imageMinimizerPlugins.length === 0)) {
|
|
77
|
+
minimizerPlugins.push(
|
|
78
|
+
new ImageMinimizerPlugin({
|
|
79
|
+
minimizer: {
|
|
80
|
+
implementation: ImageMinimizerPlugin.imageminMinify,
|
|
81
|
+
options: {
|
|
82
|
+
plugins: imageMinimizerPlugins,
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
})
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const webpackConfig = {
|
|
90
|
+
mode: 'production',
|
|
91
|
+
devtool: 'hidden-source-map',
|
|
92
|
+
context: appDirectory,
|
|
93
|
+
entry: {
|
|
94
|
+
ui: './src/ui',
|
|
95
|
+
proto: './src/proto',
|
|
96
|
+
},
|
|
97
|
+
output: {
|
|
98
|
+
path: path.resolve(appDirectory, 'public', 'assets'),
|
|
99
|
+
filename: 'js/[name].min.js',
|
|
100
|
+
chunkFilename: 'js/chunks/[name]-[contenthash:7].min.js',
|
|
101
|
+
publicPath: '/assets/',
|
|
102
|
+
},
|
|
103
|
+
resolve: {
|
|
104
|
+
symlinks: false,
|
|
105
|
+
},
|
|
106
|
+
module: {
|
|
107
|
+
rules: [],
|
|
108
|
+
},
|
|
109
|
+
plugins: [new CaseSensitivePathsPlugin({ debug: false }), new WebpackBar()],
|
|
110
|
+
optimization: {
|
|
111
|
+
moduleIds: 'deterministic',
|
|
112
|
+
chunkIds: 'deterministic',
|
|
113
|
+
runtimeChunk: false,
|
|
114
|
+
splitChunks: {
|
|
115
|
+
chunks: 'all',
|
|
116
|
+
minSize: 3000,
|
|
117
|
+
cacheGroups: {
|
|
118
|
+
default: false,
|
|
119
|
+
defaultVendors: false,
|
|
120
|
+
vendors: {
|
|
121
|
+
test: /[\\/]node_modules[\\/].*\.(js|jsx|mjs|ts|tsx)$/,
|
|
122
|
+
chunks: (chunk) => chunk.canBeInitial() && chunk.name && chunk.name !== 'proto',
|
|
123
|
+
name: 'vendors',
|
|
124
|
+
enforce: true,
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
minimizer: minimizerPlugins,
|
|
129
|
+
},
|
|
130
|
+
stats: {
|
|
131
|
+
preset: 'errors-warnings',
|
|
132
|
+
assets: true,
|
|
133
|
+
assetsSort: 'size',
|
|
134
|
+
children: false,
|
|
135
|
+
chunks: false,
|
|
136
|
+
modules: false,
|
|
137
|
+
colors: true,
|
|
138
|
+
entrypoints: true,
|
|
139
|
+
errors: true,
|
|
140
|
+
errorDetails: true,
|
|
141
|
+
hash: false,
|
|
142
|
+
builtAt: false,
|
|
143
|
+
timings: true,
|
|
144
|
+
performance: true,
|
|
145
|
+
warnings: true,
|
|
146
|
+
},
|
|
147
|
+
performance: {
|
|
148
|
+
hints: 'warning',
|
|
149
|
+
maxEntrypointSize: 760 * 1024,
|
|
150
|
+
maxAssetSize: 380 * 1024,
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
const theme = options.features.theme ? options.features.theme : false;
|
|
154
|
+
if (theme) {
|
|
155
|
+
webpackConfig.entry.ui = `./src/ui.${theme}`;
|
|
156
|
+
webpackConfig.output.path = path.resolve(webpackConfig.output.path, theme);
|
|
157
|
+
webpackConfig.output.publicPath = `${webpackConfig.output.publicPath}${theme}/`;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// scripts (js/ts via babel)
|
|
161
|
+
if (options.rules.script) {
|
|
162
|
+
const scriptOptions = typeof options.rules.script === 'object' ? options.rules.script : null;
|
|
163
|
+
webpackRules.addJSConfig(webpackConfig, appDirectory, scriptOptions);
|
|
164
|
+
if (scriptOptions && scriptOptions.typescript) {
|
|
165
|
+
webpackRules.addTsConfig(webpackConfig, appDirectory, scriptOptions, { isProduction: true });
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// css & scss
|
|
170
|
+
if (options.rules.style) {
|
|
171
|
+
const scssMiniCSSExtractOptions = {
|
|
172
|
+
...(options.rules.style.publicPath && { publicPath: options.rules.style.publicPath })
|
|
173
|
+
};
|
|
174
|
+
const scssLoaderOptions = {
|
|
175
|
+
sourceMap: true,
|
|
176
|
+
...(options.rules.style.sassOptions && { sassOptions: options.rules.style.sassOptions }),
|
|
177
|
+
};
|
|
178
|
+
webpackConfig.module.rules.push({
|
|
179
|
+
test: /\.s?css$/,
|
|
180
|
+
use: [
|
|
181
|
+
{
|
|
182
|
+
loader: MiniCssExtractPlugin.loader,
|
|
183
|
+
options: scssMiniCSSExtractOptions,
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
loader: require.resolve('css-loader'),
|
|
187
|
+
options: {
|
|
188
|
+
importLoaders: 2,
|
|
189
|
+
sourceMap: true,
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
loader: require.resolve('postcss-loader'),
|
|
194
|
+
options: {
|
|
195
|
+
sourceMap: true,
|
|
196
|
+
postcssOptions: () => {
|
|
197
|
+
return {
|
|
198
|
+
plugins: [
|
|
199
|
+
require('autoprefixer')({
|
|
200
|
+
// @see autoprefixer options: https://github.com/postcss/autoprefixer#options
|
|
201
|
+
// flexbox: 'no-2009' will add prefixes only for final and IE versions of specification.
|
|
202
|
+
flexbox: 'no-2009',
|
|
203
|
+
// grid: 'autoplace': enable autoprefixer grid translations and include autoplacement support.
|
|
204
|
+
// not enabled - use `/* autoprefixer grid: autoplace */` in your css file
|
|
205
|
+
}),
|
|
206
|
+
require('cssnano'),
|
|
207
|
+
],
|
|
208
|
+
};
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
loader: require.resolve('resolve-url-loader'),
|
|
214
|
+
options: {
|
|
215
|
+
sourceMap: true,
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
loader: require.resolve('sass-loader'),
|
|
220
|
+
options: scssLoaderOptions,
|
|
221
|
+
},
|
|
222
|
+
],
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
webpackConfig.plugins.push(
|
|
226
|
+
new MiniCssExtractPlugin({
|
|
227
|
+
filename: 'css/[name].min.css',
|
|
228
|
+
chunkFilename: 'css/chunks/[name]-[contenthash:7].min.css',
|
|
229
|
+
}),
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// handlebars precompiled templates
|
|
234
|
+
if (options.rules.hbs) {
|
|
235
|
+
const hbsRule = {
|
|
236
|
+
test: /\.hbs$/,
|
|
237
|
+
use: {
|
|
238
|
+
loader: require.resolve('handlebars-loader'),
|
|
239
|
+
// options: {
|
|
240
|
+
// helperDirs: [
|
|
241
|
+
// path.resolve(__dirname, '../../app/templating/hbs/helpers'),
|
|
242
|
+
// ],
|
|
243
|
+
// knownHelpers: [],
|
|
244
|
+
// runtime: '',
|
|
245
|
+
// partialDirs: ''
|
|
246
|
+
// },
|
|
247
|
+
},
|
|
248
|
+
};
|
|
249
|
+
webpackConfig.module.rules.push(utils.getEnrichedConfig(hbsRule, options.rules.hbs));
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// woff fonts (for example, in CSS files)
|
|
253
|
+
if (options.rules.woff) {
|
|
254
|
+
const woffRule = {
|
|
255
|
+
test: /.(woff(2)?)(\?[a-z0-9]+)?$/,
|
|
256
|
+
type: 'asset/resource',
|
|
257
|
+
generator: {
|
|
258
|
+
filename: 'media/fonts/[name]-[contenthash:7].[ext]',
|
|
259
|
+
},
|
|
260
|
+
};
|
|
261
|
+
webpackConfig.module.rules.push(utils.getEnrichedConfig(woffRule, options.rules.woff));
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// different font types (legacy - eg. used in older library css)
|
|
265
|
+
if (options.rules.font) {
|
|
266
|
+
const fontRule = {
|
|
267
|
+
test: /\.(eot|svg|ttf|woff|woff2)([?#]+[A-Za-z0-9-_]*)*$/,
|
|
268
|
+
type: 'asset',
|
|
269
|
+
parser: {
|
|
270
|
+
dataUrlCondition: {
|
|
271
|
+
maxSize: 2 * 1028,
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
generator: {
|
|
275
|
+
filename: 'media/font/[name]-[contenthash:7].[ext]',
|
|
276
|
+
},
|
|
277
|
+
};
|
|
278
|
+
webpackConfig.module.rules.push(utils.getEnrichedConfig(fontRule, options.rules.font));
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// images
|
|
282
|
+
if (options.rules.image) {
|
|
283
|
+
const imageRule = {
|
|
284
|
+
test: /\.(png|jpg|gif|svg)$/,
|
|
285
|
+
type: 'asset',
|
|
286
|
+
parser: {
|
|
287
|
+
dataUrlCondition: {
|
|
288
|
+
maxSize: 1028,
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
generator: {
|
|
292
|
+
filename: 'media/[ext]/[name]-[contenthash:7].[ext]',
|
|
293
|
+
},
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
webpackConfig.module.rules.push(utils.getEnrichedConfig(imageRule, options.rules.image));
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// feature banner (enabled by default)
|
|
300
|
+
if (!options.features.banner === false) {
|
|
301
|
+
webpackConfig.plugins.push(new webpack.BannerPlugin({ banner, entryOnly: true }));
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// feature bundle analyzer
|
|
305
|
+
if (options.features.bundleAnalyzer) {
|
|
306
|
+
webpackConfig.plugins.push(new BundleAnalyzerPlugin());
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return webpackConfig;
|
|
310
|
+
};
|
|
311
|
+
module.exports.appDirectory = appDirectory;
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
// developed for @nitro/webpack with infos & outline from:
|
|
2
|
-
// https://stackoverflow.com/questions/54320025/tap-into-webpack-resolve-loader-to-add-fallback
|
|
3
|
-
|
|
4
|
-
class DynamicAliasResolver {
|
|
5
|
-
constructor({ search, replace /*, fallback*/ }) {
|
|
6
|
-
this.search = search;
|
|
7
|
-
this.replace = replace;
|
|
8
|
-
// this.fallback = fallback;
|
|
9
|
-
this.filterFunction =
|
|
10
|
-
this.search instanceof RegExp ? (value) => search.test(value) : (value) => value.indexOf(search) !== -1;
|
|
11
|
-
}
|
|
12
|
-
apply(resolver) {
|
|
13
|
-
// current & next hook
|
|
14
|
-
const source = 'resolve';
|
|
15
|
-
const target = resolver.ensureHook('parsedResolve');
|
|
16
|
-
|
|
17
|
-
resolver.getHook(source).tapAsync('DynamicAliasResolver', (request, resolveContext, cb) => {
|
|
18
|
-
// change request if we find search term
|
|
19
|
-
if (this.filterFunction(request.request)) {
|
|
20
|
-
// possible improvement: check for existing file and use fallback
|
|
21
|
-
request.request = request.request.replace(this.search, this.replace);
|
|
22
|
-
// continue to the next hook
|
|
23
|
-
return resolver.doResolve(target, request, null, resolveContext, cb);
|
|
24
|
-
}
|
|
25
|
-
// continue
|
|
26
|
-
return cb();
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
module.exports = DynamicAliasResolver;
|