@roots/bud-build 2023.5.12 → 2023.5.22

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.
@@ -1 +1,3 @@
1
- export const experiments = async ({ hooks }) => hooks.filter(`build.experiments`, undefined);
1
+ export const experiments = async ({ hooks }) => hooks.filter(`build.experiments`, {
2
+ backCompat: false,
3
+ });
@@ -1 +1 @@
1
- export const externalsType = async (app) => `var`;
1
+ export const externalsType = async (app) => undefined;
@@ -19,4 +19,8 @@ const getRules = ({ filter, path, rules }) => [
19
19
  ...filter(`build.module.rules.after`, []),
20
20
  ];
21
21
  const getNoParse = (filter) => filter(`build.module.noParse`, undefined);
22
- const getUnsafeCache = (filter) => filter(`build.module.unsafeCache`, false);
22
+ /**
23
+ * By leaving undefined, webpack will strongly cache parsed modules from node_modules
24
+ * but leave the rest. This is the default behavior.
25
+ */
26
+ const getUnsafeCache = (filter) => filter(`build.module.unsafeCache`, undefined);
@@ -1,10 +1,20 @@
1
- export const optimization = async ({ hooks: { filter }, isDevelopment, isProduction, }) => filter(`build.optimization`, {
1
+ export const optimization = async ({ hooks: { filter }, isDevelopment, isProduction, mode, }) => filter(`build.optimization`, {
2
2
  emitOnErrors: filter(`build.optimization.emitOnErrors`, isDevelopment),
3
+ innerGraph: filter(`build.optimization.innerGraph`, isProduction),
4
+ mergeDuplicateChunks: filter(`build.optimization.mergeDuplicateChunks`, isProduction),
3
5
  minimize: filter(`build.optimization.minimize`, isProduction),
4
6
  minimizer: filter(`build.optimization.minimizer`, []),
5
7
  moduleIds: filter(`build.optimization.moduleIds`, `named`),
6
- removeEmptyChunks: filter(`build.optimization.removeEmptyChunks`, false),
8
+ nodeEnv: filter(`build.optimization.nodeEnv`, mode),
9
+ removeEmptyChunks: filter(`build.optimization.removeEmptyChunks`, isProduction),
10
+ /**
11
+ * Will be new default in webpack 6
12
+ * @see {@link https://webpack.js.org/configuration/optimization/#optimizationremoveavailablemodules}
13
+ */
14
+ removeAvailableModules: filter(`build.optimization.removeAvailableModules`, false),
7
15
  runtimeChunk: filter(`build.optimization.runtimeChunk`, false),
16
+ sideEffects: filter(`build.optimization.sideEffects`, isProduction),
8
17
  splitChunks: filter(`build.optimization.splitChunks`, false),
18
+ providedExports: filter(`build.optimization.providedExports`, isProduction),
9
19
  usedExports: filter(`build.optimization.usedExports`, isProduction),
10
20
  });
@@ -10,7 +10,7 @@ export const output = async ({ hooks: { filter }, isProduction, path, relPath, }
10
10
  filename: filename({ filter, relPath }),
11
11
  module: filter(`build.output.module`, false),
12
12
  path: filter(`build.output.path`, path(`@dist`)),
13
- pathinfo: filter(`build.output.pathinfo`),
13
+ pathinfo: filter(`build.output.pathinfo`, false),
14
14
  publicPath: filter(`build.output.publicPath`, `auto`),
15
15
  scriptType: filter(`build.output.scriptType`, isMjs(filter) ? `module` : false),
16
16
  uniqueName: filter(`build.output.uniqueName`, `@roots/bud`),
@@ -1 +1 @@
1
- export const performance = async ({ hooks }) => hooks.filter(`build.performance`, { hints: false });
1
+ export const performance = async ({ hooks }) => hooks.filter(`build.performance`, false);
@@ -1 +1 @@
1
- export const profile = async (app) => app.hooks.filter(`build.profile`, undefined);
1
+ export const profile = async (bud) => bud.hooks.filter(`build.profile`, bud.context.debug);
@@ -1,29 +1,21 @@
1
1
  export const resolve = async (bud) => {
2
- const modules = await getModules(bud);
3
- const value = {
4
- alias: await getAlias(bud),
5
- extensions: getExtensions(bud),
6
- modules,
7
- };
8
- return await bud.hooks.filterAsync(`build.resolve`, value);
2
+ return await bud.hooks.filterAsync(`build.resolve`, {
3
+ alias: {
4
+ [`@src`]: bud.path(`@src`),
5
+ ...(await bud.hooks.filterAsync(`build.resolve.alias`, {})),
6
+ },
7
+ extensionAlias: await bud.hooks.filterAsync(`build.resolve.extensionAlias`, {
8
+ [`.js`]: [`.ts`, `.tsx`, `.js`],
9
+ [`.mjs`]: [`.mts`, `.mtx`, `.mjs`],
10
+ }),
11
+ extensions: Array.from(bud.hooks.filter(`build.resolve.extensions`, new Set([`.js`, `.mjs`, `.jsx`, `.cjs`, `.css`]))),
12
+ modules: await bud.hooks.filterAsync(`build.resolve.modules`, [
13
+ bud.hooks.filter(`location.@src`),
14
+ bud.hooks.filter(`location.@modules`),
15
+ ]),
16
+ /**
17
+ * Leave `undefined` to use webpack default (true in dev, false in production)
18
+ */
19
+ unsafeCache: bud.hooks.filter(`build.module.unsafeCache`, undefined),
20
+ });
9
21
  };
10
- const getAlias = async (bud) => await bud.hooks.filterAsync(`build.resolve.alias`, {
11
- '@src': bud.path(`@src`),
12
- });
13
- const getExtensions = (bud) => Array.from(bud.hooks.filter(`build.resolve.extensions`, new Set([
14
- `.mjs`,
15
- `.js`,
16
- `.jsx`,
17
- `.css`,
18
- `.json`,
19
- `.wasm`,
20
- `.yml`,
21
- `.yaml`,
22
- `.xml`,
23
- `.toml`,
24
- `.csv`,
25
- ])));
26
- const getModules = async (bud) => await bud.hooks.filterAsync(`build.resolve.modules`, [
27
- bud.hooks.filter(`location.@src`),
28
- bud.hooks.filter(`location.@modules`),
29
- ]);
@@ -1,3 +1,3 @@
1
- export const resolveLoader = async (bud) => bud.hooks.filter(`build.resolveLoader`, {
2
- alias: {},
1
+ export const resolveLoader = async ({ hooks }) => hooks.filter(`build.resolveLoader`, {
2
+ alias: hooks.filter(`build.resolveLoader.alias`, {}),
3
3
  });
@@ -1,5 +1,10 @@
1
- export const snapshot = async (app) => app.hooks.filter(`build.snapshot`, {
2
- managedPaths: app.hooks.filter(`build.snapshot.managedPaths`, [
3
- ...new Set([app.path(`@modules`)]),
1
+ export const snapshot = async ({ env, hooks, path }) => hooks.filter(`build.snapshot`, {
2
+ immutablePaths: hooks.filter(`build.snapshot.immutablePaths`, []),
3
+ managedPaths: hooks.filter(`build.snapshot.managedPaths`, [
4
+ ...new Set([path(`@modules`)]),
4
5
  ]),
6
+ buildDependencies: hooks.filter(`build.snapshot.buildDependencies`, env.isTrue(`CI`) ? { hash: true } : { timestamp: true }),
7
+ module: hooks.filter(`build.snapshot.module`, env.isTrue(`CI`) ? { hash: true } : { timestamp: true }),
8
+ resolve: hooks.filter(`build.snapshot.resolve`, env.isTrue(`CI`) ? { hash: true } : { timestamp: true }),
9
+ resolveBuildDependencies: hooks.filter(`build.snapshot.resolveBuildDependencies`, env.isTrue(`CI`) ? { hash: true } : { timestamp: true }),
5
10
  });
@@ -48,7 +48,7 @@ export const minicss = async ({ makeItem }) => makeItem()
48
48
  .setLoader(`minicss`)
49
49
  .setIdent(`minicss`)
50
50
  .setOptions(app => ({
51
- publicPath: app.hooks.filter(`build.output.publicPath`),
51
+ publicPath: app.publicPath(),
52
52
  }));
53
53
  /**
54
54
  * Raw loader
@@ -1,4 +1,7 @@
1
1
  export const js = async ({ filter, makeRule, path }) => makeRule()
2
2
  .setTest(filter(`pattern.js`))
3
3
  .setInclude([() => path(`@src`)])
4
- .setUse([]);
4
+ .setType(`javascript/auto`)
5
+ .setResolve({
6
+ fullySpecified: false,
7
+ });
@@ -3,4 +3,6 @@ export const json = async ({ filter, makeRule, path }) => makeRule()
3
3
  .setType(`json`)
4
4
  .setInclude([() => path()])
5
5
  .setTest(filter(`pattern.json`))
6
- .setParser({ parse: json5.parse });
6
+ .setParser({
7
+ parse: json5.parse,
8
+ });
@@ -3,4 +3,6 @@ export const toml = async ({ filter, makeRule, path }) => makeRule()
3
3
  .setType(`json`)
4
4
  .setInclude([() => path()])
5
5
  .setTest(() => filter(`pattern.toml`))
6
- .setParser({ parse: tomlParser.parse });
6
+ .setParser({
7
+ parse: tomlParser.parse,
8
+ });
@@ -6,10 +6,14 @@ import Base from '../shared/base.js';
6
6
  * RuleSetRule
7
7
  */
8
8
  declare class Rule extends Base implements Interface {
9
+ /**
10
+ * RuleSetRule resolve
11
+ */
12
+ resolve?: Options[`resolve`];
9
13
  /**
10
14
  * RuleSetRule test
11
15
  */
12
- test: Options['test'];
16
+ test: Options[`test`];
13
17
  /**
14
18
  * RuleSetRule use
15
19
  */
@@ -17,73 +21,81 @@ declare class Rule extends Base implements Interface {
17
21
  /**
18
22
  * RuleSetRule include
19
23
  */
20
- include?: Options['include'];
24
+ include?: Options[`include`];
21
25
  /**
22
26
  * RuleSetRule exclude
23
27
  */
24
- exclude?: Options['exclude'];
28
+ exclude?: Options[`exclude`];
25
29
  /**
26
30
  * RuleSetRule type
27
31
  */
28
- type?: Options['type'];
32
+ type?: Options[`type`];
29
33
  /**
30
34
  * RuleSetRule resourceQuery
31
35
  */
32
- resourceQuery?: Options['resourceQuery'];
36
+ resourceQuery?: Options[`resourceQuery`];
33
37
  /**
34
38
  * RuleSetRule parser
35
39
  */
36
- parser?: Options['parser'];
40
+ parser?: Options[`parser`];
37
41
  /**
38
42
  * RuleSetRule generator
39
43
  */
40
- generator?: Options['generator'];
44
+ generator?: Options[`generator`];
41
45
  /**
42
46
  * Class constructor
43
47
  */
44
48
  constructor(_app: () => Bud, options?: Options);
45
49
  /**
46
- * Test value
50
+ * Set resolve value
51
+ */
52
+ getResolve(): Output[`resolve`];
53
+ /**
54
+ * Set resolve value
55
+ */
56
+ setResolve(resolve: Options[`resolve`]): this;
57
+ /**
58
+ * Get `test` value
47
59
  */
48
60
  getTest(): Output['test'];
49
61
  /**
50
- * Set test value
62
+ * Set `test` value
51
63
  */
52
64
  setTest(test: Options['test']): this;
53
65
  /**
54
- * Get parser value
66
+ * Get `parser` value
55
67
  */
56
68
  getParser(): Output['parser'];
57
69
  /**
58
- * Set parser value
70
+ * Set `parser` value
59
71
  */
60
72
  setParser(parser: Interface['parser']): this;
61
73
  /**
62
- * Get use value
74
+ * Get `use` value
63
75
  */
64
76
  getUse(): Options[`use`];
65
77
  /**
66
- * Set use value
78
+ * Set `use` value
67
79
  */
68
80
  setUse(use: Options[`use`] | ((use: Options[`use`]) => Options[`use`])): this;
69
81
  /**
70
- * Get include value
82
+ * Get `include` value
71
83
  */
72
84
  getInclude(): Array<string | RegExp>;
73
85
  /**
74
- * Set include value
86
+ * Set `include` value
75
87
  */
76
88
  setInclude(includes: Options['include']): this;
77
89
  /**
78
- * Get include value
90
+ * Get `include` value
79
91
  */
80
92
  getResourceQuery(): Output[`resourceQuery`];
81
93
  /**
82
- * Set include value
94
+ * Set `include` value
83
95
  */
84
96
  setResourceQuery(query: Options['resourceQuery']): this;
85
97
  /**
86
- * Get exclude value
98
+ * Get `exclude` value
87
99
  */
88
100
  getExclude(): Array<string | RegExp>;
89
101
  /**
@@ -91,7 +103,7 @@ declare class Rule extends Base implements Interface {
91
103
  */
92
104
  setExclude(excludes: Options['exclude'] | ((excludes: Options['exclude']) => Options['exclude'])): this;
93
105
  /**
94
- * Get type value
106
+ * Get `type` value
95
107
  */
96
108
  getType(): string;
97
109
  /**
@@ -114,4 +126,4 @@ declare class Rule extends Base implements Interface {
114
126
  toWebpack(): Output & RuleSetRule;
115
127
  }
116
128
  export { Rule };
117
- export { Interface, Options, Output, Parser };
129
+ export type { Interface, Options, Output, Parser };
package/lib/rule/index.js CHANGED
@@ -22,74 +22,92 @@ class Rule extends Base {
22
22
  this.setType(options.type);
23
23
  this.setParser(options.parser);
24
24
  this.setGenerator(options.generator);
25
+ this.setResolve(options.resolve);
25
26
  }
26
27
  /**
27
- * Test value
28
+ * Set resolve value
29
+ */
30
+ getResolve() {
31
+ return this.unwrap(this.resolve);
32
+ }
33
+ /**
34
+ * Set resolve value
35
+ */
36
+ setResolve(resolve) {
37
+ this.resolve = resolve;
38
+ return this;
39
+ }
40
+ /**
41
+ * Get `test` value
28
42
  */
29
43
  getTest() {
30
44
  return this.unwrap(this.test);
31
45
  }
32
46
  /**
33
- * Set test value
47
+ * Set `test` value
34
48
  */
35
49
  setTest(test) {
36
50
  this.test = test;
37
51
  return this;
38
52
  }
39
53
  /**
40
- * Get parser value
54
+ * Get `parser` value
41
55
  */
42
56
  getParser() {
43
57
  return this.unwrap(this.parser);
44
58
  }
45
59
  /**
46
- * Set parser value
60
+ * Set `parser` value
47
61
  */
48
62
  setParser(parser) {
49
63
  this.parser = this.wrap(parser);
50
64
  return this;
51
65
  }
52
66
  /**
53
- * Get use value
67
+ * Get `use` value
54
68
  */
55
69
  getUse() {
56
70
  return this.use;
57
71
  }
58
72
  /**
59
- * Set use value
73
+ * Set `use` value
60
74
  */
61
75
  setUse(use) {
62
76
  this.use = isFunction(use) ? use(this.getUse()) : use;
63
77
  return this;
64
78
  }
65
79
  /**
66
- * Get include value
80
+ * Get `include` value
67
81
  */
68
82
  getInclude() {
69
83
  return this.include?.map(item => isFunction(item) ? item(this.app) : item);
70
84
  }
71
85
  /**
72
- * Set include value
86
+ * Set `include` value
73
87
  */
74
88
  setInclude(includes) {
75
89
  this.include = isFunction(includes) ? includes(this.include) : includes;
76
90
  return this;
77
91
  }
78
92
  /**
79
- * Get include value
93
+ * Get `include` value
80
94
  */
81
95
  getResourceQuery() {
82
- return this.resourceQuery;
96
+ return isFunction(this.resourceQuery)
97
+ ? this.resourceQuery(this.app)
98
+ : this.resourceQuery;
83
99
  }
84
100
  /**
85
- * Set include value
101
+ * Set `include` value
86
102
  */
87
103
  setResourceQuery(query) {
88
- this.resourceQuery = query;
104
+ this.resourceQuery = isFunction(query)
105
+ ? query(this.resourceQuery)
106
+ : query;
89
107
  return this;
90
108
  }
91
109
  /**
92
- * Get exclude value
110
+ * Get `exclude` value
93
111
  */
94
112
  getExclude() {
95
113
  return this.exclude?.map(this.unwrap);
@@ -102,7 +120,7 @@ class Rule extends Base {
102
120
  return this;
103
121
  }
104
122
  /**
105
- * Get type value
123
+ * Get `type` value
106
124
  */
107
125
  getType() {
108
126
  return this.unwrap(this.type);
@@ -146,6 +164,7 @@ class Rule extends Base {
146
164
  resourceQuery: this.getResourceQuery(),
147
165
  include: this.getInclude(),
148
166
  exclude: this.getExclude(),
167
+ resolve: this.getResolve(),
149
168
  }).reduce((a, [k, v]) => {
150
169
  if (v === undefined)
151
170
  return a;
@@ -154,6 +173,12 @@ class Rule extends Base {
154
173
  return output;
155
174
  }
156
175
  }
176
+ __decorate([
177
+ bind,
178
+ __metadata("design:type", Function),
179
+ __metadata("design:paramtypes", [Object]),
180
+ __metadata("design:returntype", Object)
181
+ ], Rule.prototype, "setResolve", null);
157
182
  __decorate([
158
183
  bind,
159
184
  __metadata("design:type", Function),
package/lib/service.d.ts CHANGED
@@ -5,7 +5,8 @@ import type { Configuration } from '@roots/bud-support/webpack';
5
5
  import { register } from './handlers/register.js';
6
6
  import { Item } from './item/index.js';
7
7
  import { Loader } from './loader/index.js';
8
- import { Options as RuleOptions, Rule } from './rule/index.js';
8
+ import type { Options as RuleOptions } from './rule/index.js';
9
+ import { Rule } from './rule/index.js';
9
10
  /**
10
11
  * Webpack configuration builder class
11
12
  */
@@ -33,7 +34,7 @@ export declare class Build extends Service implements Base.Service {
33
34
  * `loaders`, `items`, and `rules` are instantiated dumbly
34
35
  * because it is painful to think about how to map the typings..
35
36
  */
36
- register?: typeof register;
37
+ register: typeof register;
37
38
  /**
38
39
  * Make webpack configuration
39
40
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@roots/bud-build",
3
- "version": "2023.5.12",
3
+ "version": "2023.5.22",
4
4
  "description": "bud.js core module",
5
5
  "engines": {
6
6
  "node": ">=16"
@@ -85,14 +85,14 @@
85
85
  "types": "./lib/index.d.ts",
86
86
  "module": "./lib/index.js",
87
87
  "devDependencies": {
88
- "@roots/bud-api": "2023.5.12",
89
- "@roots/bud-hooks": "2023.5.12",
88
+ "@roots/bud-api": "2023.5.22",
89
+ "@roots/bud-hooks": "2023.5.22",
90
90
  "@skypack/package-check": "0.2.2",
91
- "@types/node": "18.16.6"
91
+ "@types/node": "18.16.12"
92
92
  },
93
93
  "dependencies": {
94
- "@roots/bud-framework": "2023.5.12",
95
- "@roots/bud-support": "2023.5.12",
94
+ "@roots/bud-framework": "2023.5.22",
95
+ "@roots/bud-support": "2023.5.22",
96
96
  "tslib": "2.5.0"
97
97
  },
98
98
  "volta": {
@@ -1,4 +1,6 @@
1
1
  import type {Factory} from './index.js'
2
2
 
3
3
  export const experiments: Factory<`experiments`> = async ({hooks}) =>
4
- hooks.filter(`build.experiments`, undefined)
4
+ hooks.filter(`build.experiments`, {
5
+ backCompat: false,
6
+ })
@@ -1,3 +1,4 @@
1
1
  import type {Factory} from './index.js'
2
2
 
3
- export const externalsType: Factory<`externalsType`> = async app => `var`
3
+ export const externalsType: Factory<`externalsType`> = async app =>
4
+ undefined
@@ -80,13 +80,15 @@ describe(`bud.build.config`, function () {
80
80
  it(`should have expected resolve.extensions default`, async () => {
81
81
  expect(build.config.resolve?.extensions?.sort()).toEqual(
82
82
  expect.arrayContaining([
83
+ `.cjs`,
83
84
  `.css`,
85
+ `.cts`,
84
86
  `.js`,
85
- `.json`,
86
87
  `.jsx`,
87
88
  `.mjs`,
88
- `.wasm`,
89
- `.yml`,
89
+ `.mts`,
90
+ `.ts`,
91
+ `.tsx`,
90
92
  ]),
91
93
  )
92
94
  })
@@ -41,5 +41,9 @@ const getRules = ({filter, path, rules}: Props) => [
41
41
  const getNoParse = (filter: Props[`filter`]) =>
42
42
  filter(`build.module.noParse`, undefined)
43
43
 
44
+ /**
45
+ * By leaving undefined, webpack will strongly cache parsed modules from node_modules
46
+ * but leave the rest. This is the default behavior.
47
+ */
44
48
  const getUnsafeCache = (filter: Props[`filter`]) =>
45
- filter(`build.module.unsafeCache`, false)
49
+ filter(`build.module.unsafeCache`, undefined)
@@ -4,17 +4,37 @@ export const optimization: Factory<`optimization`> = async ({
4
4
  hooks: {filter},
5
5
  isDevelopment,
6
6
  isProduction,
7
+ mode,
7
8
  }) =>
8
9
  filter(`build.optimization`, {
9
10
  emitOnErrors: filter(`build.optimization.emitOnErrors`, isDevelopment),
11
+ innerGraph: filter(`build.optimization.innerGraph`, isProduction),
12
+ mergeDuplicateChunks: filter(
13
+ `build.optimization.mergeDuplicateChunks`,
14
+ isProduction,
15
+ ),
10
16
  minimize: filter(`build.optimization.minimize`, isProduction),
11
17
  minimizer: filter(`build.optimization.minimizer`, []),
12
18
  moduleIds: filter(`build.optimization.moduleIds`, `named`),
19
+ nodeEnv: filter(`build.optimization.nodeEnv`, mode),
13
20
  removeEmptyChunks: filter(
14
21
  `build.optimization.removeEmptyChunks`,
22
+ isProduction,
23
+ ),
24
+ /**
25
+ * Will be new default in webpack 6
26
+ * @see {@link https://webpack.js.org/configuration/optimization/#optimizationremoveavailablemodules}
27
+ */
28
+ removeAvailableModules: filter(
29
+ `build.optimization.removeAvailableModules`,
15
30
  false,
16
31
  ),
17
32
  runtimeChunk: filter(`build.optimization.runtimeChunk`, false),
33
+ sideEffects: filter(`build.optimization.sideEffects`, isProduction),
18
34
  splitChunks: filter(`build.optimization.splitChunks`, false),
35
+ providedExports: filter(
36
+ `build.optimization.providedExports`,
37
+ isProduction,
38
+ ),
19
39
  usedExports: filter(`build.optimization.usedExports`, isProduction),
20
40
  })
@@ -18,7 +18,7 @@ export const output: Factory<`output`> = async ({
18
18
  filename: filename({filter, relPath}),
19
19
  module: filter(`build.output.module`, false),
20
20
  path: filter(`build.output.path`, path(`@dist`)),
21
- pathinfo: filter(`build.output.pathinfo`),
21
+ pathinfo: filter(`build.output.pathinfo`, false),
22
22
  publicPath: filter(`build.output.publicPath`, `auto`),
23
23
  scriptType: filter(
24
24
  `build.output.scriptType`,
@@ -1,4 +1,4 @@
1
1
  import type {Factory} from './index.js'
2
2
 
3
3
  export const performance: Factory<`performance`> = async ({hooks}) =>
4
- hooks.filter(`build.performance`, {hints: false})
4
+ hooks.filter(`build.performance`, false)
@@ -1,4 +1,4 @@
1
1
  import type {Factory} from './index.js'
2
2
 
3
- export const profile: Factory<`profile`> = async app =>
4
- app.hooks.filter(`build.profile`, undefined)
3
+ export const profile: Factory<`profile`> = async bud =>
4
+ bud.hooks.filter(`build.profile`, bud.context.debug)
@@ -1,45 +1,31 @@
1
- import type {Bud} from '@roots/bud-framework'
2
-
3
1
  import type {Factory} from './index.js'
4
2
 
5
3
  export const resolve: Factory<`resolve`> = async bud => {
6
- const modules = await getModules(bud)
7
- const value = {
8
- alias: await getAlias(bud),
9
- extensions: getExtensions(bud),
10
- modules,
11
- }
12
-
13
- return await bud.hooks.filterAsync(`build.resolve`, value)
14
- }
15
-
16
- const getAlias = async (bud: Bud) =>
17
- await bud.hooks.filterAsync(`build.resolve.alias`, {
18
- '@src': bud.path(`@src`),
19
- })
20
-
21
- const getExtensions = (bud: Bud) =>
22
- Array.from(
23
- bud.hooks.filter(
24
- `build.resolve.extensions`,
25
- new Set([
26
- `.mjs`,
27
- `.js`,
28
- `.jsx`,
29
- `.css`,
30
- `.json`,
31
- `.wasm`,
32
- `.yml`,
33
- `.yaml`,
34
- `.xml`,
35
- `.toml`,
36
- `.csv`,
37
- ]),
4
+ return await bud.hooks.filterAsync(`build.resolve`, {
5
+ alias: {
6
+ [`@src`]: bud.path(`@src`),
7
+ ...(await bud.hooks.filterAsync(`build.resolve.alias`, {})),
8
+ },
9
+ extensionAlias: await bud.hooks.filterAsync(
10
+ `build.resolve.extensionAlias`,
11
+ {
12
+ [`.js`]: [`.ts`, `.tsx`, `.js`],
13
+ [`.mjs`]: [`.mts`, `.mtx`, `.mjs`],
14
+ },
38
15
  ),
39
- )
40
-
41
- const getModules = async (bud: Bud) =>
42
- await bud.hooks.filterAsync(`build.resolve.modules`, [
43
- bud.hooks.filter(`location.@src`),
44
- bud.hooks.filter(`location.@modules`),
45
- ])
16
+ extensions: Array.from(
17
+ bud.hooks.filter(
18
+ `build.resolve.extensions`,
19
+ new Set([`.js`, `.mjs`, `.jsx`, `.cjs`, `.css`]),
20
+ ),
21
+ ),
22
+ modules: await bud.hooks.filterAsync(`build.resolve.modules`, [
23
+ bud.hooks.filter(`location.@src`),
24
+ bud.hooks.filter(`location.@modules`),
25
+ ]),
26
+ /**
27
+ * Leave `undefined` to use webpack default (true in dev, false in production)
28
+ */
29
+ unsafeCache: bud.hooks.filter(`build.module.unsafeCache`, undefined),
30
+ })
31
+ }
@@ -1,6 +1,6 @@
1
1
  import type {Factory} from './index.js'
2
2
 
3
- export const resolveLoader: Factory<`resolveLoader`> = async bud =>
4
- bud.hooks.filter(`build.resolveLoader`, {
5
- alias: {},
3
+ export const resolveLoader: Factory<`resolveLoader`> = async ({hooks}) =>
4
+ hooks.filter(`build.resolveLoader`, {
5
+ alias: hooks.filter(`build.resolveLoader.alias`, {}),
6
6
  })
@@ -1,8 +1,25 @@
1
1
  import type {Factory} from './index.js'
2
2
 
3
- export const snapshot: Factory<`snapshot`> = async app =>
4
- app.hooks.filter(`build.snapshot`, {
5
- managedPaths: app.hooks.filter(`build.snapshot.managedPaths`, [
6
- ...new Set([app.path(`@modules`)]),
3
+ export const snapshot: Factory<`snapshot`> = async ({env, hooks, path}) =>
4
+ hooks.filter(`build.snapshot`, {
5
+ immutablePaths: hooks.filter(`build.snapshot.immutablePaths`, []),
6
+ managedPaths: hooks.filter(`build.snapshot.managedPaths`, [
7
+ ...new Set([path(`@modules`)]),
7
8
  ]),
9
+ buildDependencies: hooks.filter(
10
+ `build.snapshot.buildDependencies`,
11
+ env.isTrue(`CI`) ? {hash: true} : {timestamp: true},
12
+ ),
13
+ module: hooks.filter(
14
+ `build.snapshot.module`,
15
+ env.isTrue(`CI`) ? {hash: true} : {timestamp: true},
16
+ ),
17
+ resolve: hooks.filter(
18
+ `build.snapshot.resolve`,
19
+ env.isTrue(`CI`) ? {hash: true} : {timestamp: true},
20
+ ),
21
+ resolveBuildDependencies: hooks.filter(
22
+ `build.snapshot.resolveBuildDependencies`,
23
+ env.isTrue(`CI`) ? {hash: true} : {timestamp: true},
24
+ ),
8
25
  })
@@ -65,7 +65,7 @@ export const minicss: Factory<Item> = async ({makeItem}) =>
65
65
  .setLoader(`minicss`)
66
66
  .setIdent(`minicss`)
67
67
  .setOptions(app => ({
68
- publicPath: app.hooks.filter(`build.output.publicPath`),
68
+ publicPath: app.publicPath(),
69
69
  }))
70
70
 
71
71
  /**
@@ -4,4 +4,7 @@ export const js: Factory = async ({filter, makeRule, path}) =>
4
4
  makeRule()
5
5
  .setTest(filter(`pattern.js`))
6
6
  .setInclude([() => path(`@src`)])
7
- .setUse([])
7
+ .setType(`javascript/auto`)
8
+ .setResolve({
9
+ fullySpecified: false,
10
+ })
@@ -7,4 +7,6 @@ export const json: Factory = async ({filter, makeRule, path}) =>
7
7
  .setType(`json`)
8
8
  .setInclude([() => path()])
9
9
  .setTest(filter(`pattern.json`))
10
- .setParser({parse: json5.parse})
10
+ .setParser({
11
+ parse: json5.parse,
12
+ })
@@ -7,4 +7,6 @@ export const toml: Factory = async ({filter, makeRule, path}) =>
7
7
  .setType(`json`)
8
8
  .setInclude([() => path()])
9
9
  .setTest(() => filter(`pattern.toml`))
10
- .setParser({parse: tomlParser.parse})
10
+ .setParser({
11
+ parse: tomlParser.parse,
12
+ })
package/src/rule/index.ts CHANGED
@@ -16,10 +16,15 @@ import Base from '../shared/base.js'
16
16
  * RuleSetRule
17
17
  */
18
18
  class Rule extends Base implements Interface {
19
+ /**
20
+ * RuleSetRule resolve
21
+ */
22
+ public resolve?: Options[`resolve`]
23
+
19
24
  /**
20
25
  * RuleSetRule test
21
26
  */
22
- public test: Options['test']
27
+ public test: Options[`test`]
23
28
 
24
29
  /**
25
30
  * RuleSetRule use
@@ -29,32 +34,32 @@ class Rule extends Base implements Interface {
29
34
  /**
30
35
  * RuleSetRule include
31
36
  */
32
- public include?: Options['include']
37
+ public include?: Options[`include`]
33
38
 
34
39
  /**
35
40
  * RuleSetRule exclude
36
41
  */
37
- public exclude?: Options['exclude']
42
+ public exclude?: Options[`exclude`]
38
43
 
39
44
  /**
40
45
  * RuleSetRule type
41
46
  */
42
- public type?: Options['type']
47
+ public type?: Options[`type`]
43
48
 
44
49
  /**
45
50
  * RuleSetRule resourceQuery
46
51
  */
47
- public resourceQuery?: Options['resourceQuery']
52
+ public resourceQuery?: Options[`resourceQuery`]
48
53
 
49
54
  /**
50
55
  * RuleSetRule parser
51
56
  */
52
- public parser?: Options['parser']
57
+ public parser?: Options[`parser`]
53
58
 
54
59
  /**
55
60
  * RuleSetRule generator
56
61
  */
57
- public generator?: Options['generator']
62
+ public generator?: Options[`generator`]
58
63
 
59
64
  /**
60
65
  * Class constructor
@@ -72,10 +77,27 @@ class Rule extends Base implements Interface {
72
77
  this.setType(options.type)
73
78
  this.setParser(options.parser)
74
79
  this.setGenerator(options.generator)
80
+ this.setResolve(options.resolve)
81
+ }
82
+
83
+ /**
84
+ * Set resolve value
85
+ */
86
+ public getResolve(): Output[`resolve`] {
87
+ return this.unwrap(this.resolve)
75
88
  }
76
89
 
77
90
  /**
78
- * Test value
91
+ * Set resolve value
92
+ */
93
+ @bind
94
+ public setResolve(resolve: Options[`resolve`]): this {
95
+ this.resolve = resolve
96
+ return this
97
+ }
98
+
99
+ /**
100
+ * Get `test` value
79
101
  */
80
102
  @bind
81
103
  public getTest(): Output['test'] {
@@ -83,7 +105,7 @@ class Rule extends Base implements Interface {
83
105
  }
84
106
 
85
107
  /**
86
- * Set test value
108
+ * Set `test` value
87
109
  */
88
110
  @bind
89
111
  public setTest(test: Options['test']): this {
@@ -92,7 +114,7 @@ class Rule extends Base implements Interface {
92
114
  }
93
115
 
94
116
  /**
95
- * Get parser value
117
+ * Get `parser` value
96
118
  */
97
119
  @bind
98
120
  public getParser(): Output['parser'] {
@@ -100,7 +122,7 @@ class Rule extends Base implements Interface {
100
122
  }
101
123
 
102
124
  /**
103
- * Set parser value
125
+ * Set `parser` value
104
126
  */
105
127
  @bind
106
128
  public setParser(parser: Interface['parser']): this {
@@ -109,7 +131,7 @@ class Rule extends Base implements Interface {
109
131
  }
110
132
 
111
133
  /**
112
- * Get use value
134
+ * Get `use` value
113
135
  */
114
136
  @bind
115
137
  public getUse(): Options[`use`] {
@@ -117,7 +139,7 @@ class Rule extends Base implements Interface {
117
139
  }
118
140
 
119
141
  /**
120
- * Set use value
142
+ * Set `use` value
121
143
  */
122
144
  @bind
123
145
  public setUse(
@@ -128,7 +150,7 @@ class Rule extends Base implements Interface {
128
150
  }
129
151
 
130
152
  /**
131
- * Get include value
153
+ * Get `include` value
132
154
  */
133
155
  @bind
134
156
  public getInclude(): Array<string | RegExp> {
@@ -138,7 +160,7 @@ class Rule extends Base implements Interface {
138
160
  }
139
161
 
140
162
  /**
141
- * Set include value
163
+ * Set `include` value
142
164
  */
143
165
  @bind
144
166
  public setInclude(includes: Options['include']): this {
@@ -147,24 +169,29 @@ class Rule extends Base implements Interface {
147
169
  }
148
170
 
149
171
  /**
150
- * Get include value
172
+ * Get `include` value
151
173
  */
152
174
  @bind
153
175
  public getResourceQuery(): Output[`resourceQuery`] {
154
- return this.resourceQuery
176
+ return isFunction(this.resourceQuery)
177
+ ? this.resourceQuery(this.app)
178
+ : this.resourceQuery
155
179
  }
156
180
 
157
181
  /**
158
- * Set include value
182
+ * Set `include` value
159
183
  */
160
184
  @bind
161
185
  public setResourceQuery(query: Options['resourceQuery']): this {
162
- this.resourceQuery = query
186
+ this.resourceQuery = isFunction(query)
187
+ ? query(this.resourceQuery)
188
+ : query
189
+
163
190
  return this
164
191
  }
165
192
 
166
193
  /**
167
- * Get exclude value
194
+ * Get `exclude` value
168
195
  */
169
196
  @bind
170
197
  public getExclude(): Array<string | RegExp> {
@@ -185,7 +212,7 @@ class Rule extends Base implements Interface {
185
212
  }
186
213
 
187
214
  /**
188
- * Get type value
215
+ * Get `type` value
189
216
  */
190
217
  @bind
191
218
  public getType(): string {
@@ -242,6 +269,7 @@ class Rule extends Base implements Interface {
242
269
  resourceQuery: this.getResourceQuery(),
243
270
  include: this.getInclude(),
244
271
  exclude: this.getExclude(),
272
+ resolve: this.getResolve(),
245
273
  }).reduce((a, [k, v]) => {
246
274
  if (v === undefined) return a
247
275
  return {...a, [k]: v}
@@ -252,4 +280,4 @@ class Rule extends Base implements Interface {
252
280
  }
253
281
 
254
282
  export {Rule}
255
- export {Interface, Options, Output, Parser}
283
+ export type {Interface, Options, Output, Parser}
package/src/service.ts CHANGED
@@ -10,7 +10,8 @@ import type {Records} from './config/index.js'
10
10
  import {register} from './handlers/register.js'
11
11
  import {Item} from './item/index.js'
12
12
  import {Loader} from './loader/index.js'
13
- import {Options as RuleOptions, Rule} from './rule/index.js'
13
+ import type {Options as RuleOptions} from './rule/index.js'
14
+ import {Rule} from './rule/index.js'
14
15
 
15
16
  /**
16
17
  * Webpack configuration builder class
@@ -43,7 +44,7 @@ export class Build extends Service implements Base.Service {
43
44
  * `loaders`, `items`, and `rules` are instantiated dumbly
44
45
  * because it is painful to think about how to map the typings..
45
46
  */
46
- public override register? = register.bind(this)
47
+ public override register = register.bind(this)
47
48
 
48
49
  /**
49
50
  * Make webpack configuration