@roots/bud-build 6.13.1 → 6.14.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.
@@ -1,3 +1,7 @@
1
- export const experiments = async ({ hooks }) => hooks.filter(`build.experiments`, {
1
+ export const experiments = async ({ hooks, isDevelopment, }) => hooks.filter(`build.experiments`, {
2
2
  backCompat: false,
3
+ lazyCompilation: isDevelopment
4
+ ? { entries: false, imports: true }
5
+ : false,
6
+ topLevelAwait: true,
3
7
  });
@@ -1,4 +1,4 @@
1
- import logger from '@roots/bud-support/utilities/logger';
1
+ import logger from '@roots/bud-support/logger';
2
2
  export const infrastructureLogging = async (bud) => bud.hooks.filter(`build.infrastructureLogging`, {
3
3
  console: bud.hooks.filter(`build.infrastructureLogging.console`, {
4
4
  ...console,
@@ -1,17 +1,22 @@
1
1
  import { isMjs } from '../../helpers/isMjs.js';
2
2
  import { assetModuleFilename } from './assetModuleFilename.js';
3
- import { chunkFilename } from './chunkFilename.js';
4
3
  import { filename } from './filename.js';
5
4
  export const output = async ({ hooks: { filter }, isProduction, path, relPath, }) => filter(`build.output`, {
6
5
  assetModuleFilename: assetModuleFilename({ filter, relPath }),
7
- chunkFilename: chunkFilename({ filter, relPath }),
6
+ /**
7
+ * This should be kept undefined as documented here:
8
+ * {@see https://webpack.js.org/plugins/split-chunks-plugin/#splitchunkscachegroupscachegroupfilename}
9
+ */
10
+ // chunkFilename: chunkFilename({filter, relPath}),
8
11
  clean: filter(`build.output.clean`, isProduction),
9
12
  environment: filter(`build.output.environment`, undefined),
10
13
  filename: filename({ filter, relPath }),
14
+ hashFunction: filter(`build.output.hashFunction`, `xxhash64`),
15
+ iife: filter(`build.output.iife`, undefined),
11
16
  module: filter(`build.output.module`, false),
12
17
  path: filter(`build.output.path`, path(`@dist`)),
13
18
  pathinfo: filter(`build.output.pathinfo`, false),
14
19
  publicPath: filter(`build.output.publicPath`, `auto`),
15
- scriptType: filter(`build.output.scriptType`, isMjs(filter) ? `module` : false),
20
+ scriptType: filter(`build.output.scriptType`, isMjs(filter) ? `module` : `text/javascript`),
16
21
  uniqueName: filter(`build.output.uniqueName`, `@roots/bud`),
17
22
  });
@@ -1,2 +1,9 @@
1
1
  import { cpus } from 'node:os';
2
- export const parallelism = async ({ hooks }) => hooks.filter(`build.parallelism`, 10 * Math.max(cpus().length - 1, 1));
2
+ export const parallelism = async ({ hooks, root, }) => {
3
+ const factor = 10;
4
+ const procs = Math.min(cpus().length - 1, 1);
5
+ const comps = root.hasChildren
6
+ ? Math.min(Object.keys(root.children).length)
7
+ : 1;
8
+ return hooks.filter(`build.parallelism`, (procs * factor) / comps);
9
+ };
@@ -1,3 +1,4 @@
1
+ import isString from '@roots/bud-support/lodash/isString';
1
2
  export const resolve = async (bud) => {
2
3
  return await bud.hooks.filterAsync(`build.resolve`, {
3
4
  alias: {
@@ -12,7 +13,7 @@ export const resolve = async (bud) => {
12
13
  modules: await bud.hooks.filterAsync(`build.resolve.modules`, [
13
14
  bud.hooks.filter(`location.@src`),
14
15
  bud.hooks.filter(`location.@modules`),
15
- ]),
16
+ ].filter(v => isString(v) && v.length > 0)),
16
17
  /**
17
18
  * Leave `undefined` to use webpack default (true in dev, false in production)
18
19
  */
@@ -1,3 +1,11 @@
1
- export const resolveLoader = async ({ hooks }) => hooks.filter(`build.resolveLoader`, {
2
- alias: hooks.filter(`build.resolveLoader.alias`, {}),
1
+ export const resolveLoader = async ({ hooks, module, }) => hooks.filter(`build.resolveLoader`, {
2
+ alias: hooks.filter(`build.resolveLoader.alias`, {
3
+ 'css-loader': await module.resolve(`@roots/bud-support/css-loader`),
4
+ 'file-loader': await module.resolve(`@roots/bud-support/file-loader`),
5
+ 'html-loader': await module.resolve(`@roots/bud-support/html-loader`),
6
+ json5: await module.resolve(`@roots/bud-support/json5`),
7
+ 'mini-svg-data-uri': await module.resolve(`mini-svg-data-uri`),
8
+ 'style-loader': await module.resolve(`@roots/bud-support/style-loader`),
9
+ toml: await module.resolve(`@roots/bud-support/toml`),
10
+ }),
3
11
  });
@@ -2,7 +2,10 @@ export const stats = async (app) => app.hooks.filter(`build.stats`, app.isProduc
2
2
  ? {
3
3
  all: false,
4
4
  assets: true,
5
+ assetsSort: `size`,
6
+ builtAt: false,
5
7
  children: false,
8
+ chunks: false,
6
9
  entrypoints: true,
7
10
  errors: true,
8
11
  errorsCount: true,
package/lib/item/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { __decorate, __metadata } from "tslib";
2
+ import { basename } from 'path';
2
3
  import { bind } from '@roots/bud-support/decorators/bind';
3
4
  import isString from '@roots/bud-support/lodash/isString';
4
- import { basename } from 'path';
5
5
  import { Loader } from '../loader/index.js';
6
6
  import Base from '../shared/base.js';
7
7
  /**
package/lib/service.d.ts CHANGED
@@ -1,6 +1,6 @@
1
+ import type { Bud, Build as BudBuild } from '@roots/bud-framework';
1
2
  import type { Items, Loaders, Rules } from '@roots/bud-framework';
2
3
  import type { Configuration } from '@roots/bud-framework/config';
3
- import type * as Base from '@roots/bud-framework/services/build';
4
4
  import { Service } from '@roots/bud-framework/service';
5
5
  import type { Options as RuleOptions } from './rule/index.js';
6
6
  import { register } from './handlers/register.js';
@@ -10,7 +10,7 @@ import { Rule } from './rule/index.js';
10
10
  /**
11
11
  * Webpack configuration builder class
12
12
  */
13
- export declare class Build extends Service implements Base.Service {
13
+ export declare class Build extends Service implements BudBuild {
14
14
  /**
15
15
  * Built config object
16
16
  */
@@ -24,17 +24,14 @@ export declare class Build extends Service implements Base.Service {
24
24
  */
25
25
  loaders: Loaders;
26
26
  /**
27
- * Service register event
28
- *
29
- * @remarks
30
- * `loaders`, `items`, and `rules` are instantiated dumbly
31
- * because it is painful to think about how to map the typings..
27
+ * {@link BudBuild.register}
32
28
  */
33
- register: typeof register;
29
+ register?: typeof register;
34
30
  /**
35
31
  * Registered rules
36
32
  */
37
33
  rules: Rules;
34
+ bootstrap?(app: Bud): Promise<void>;
38
35
  /**
39
36
  * Get item
40
37
  */
package/lib/service.js CHANGED
@@ -17,25 +17,14 @@ export class Build extends Service {
17
17
  */
18
18
  config = {};
19
19
  /**
20
- * Registered items
21
- */
22
- items = {};
23
- /**
24
- * Registered loaders
25
- */
26
- loaders = {};
27
- /**
28
- * Service register event
29
- *
30
- * @remarks
31
- * `loaders`, `items`, and `rules` are instantiated dumbly
32
- * because it is painful to think about how to map the typings..
20
+ * {@link BudBuild.register}
33
21
  */
34
22
  register = register.bind(this);
35
- /**
36
- * Registered rules
37
- */
38
- rules = {};
23
+ async bootstrap(app) {
24
+ this.items = {};
25
+ this.loaders = {};
26
+ this.rules = {};
27
+ }
39
28
  /**
40
29
  * Get item
41
30
  */
package/lib/types.d.ts CHANGED
@@ -1,7 +1,11 @@
1
- import type { Item } from './item/index.js';
2
- import type { Loader } from './loader/index.js';
3
- import type { Rule } from './rule/index.js';
1
+ import type { Item } from '@roots/bud-build/item';
2
+ import type { Loader } from '@roots/bud-build/loader';
3
+ import type { Rule } from '@roots/bud-build/rule';
4
+ import type { Build } from './service.js';
4
5
  declare module '@roots/bud-framework' {
6
+ interface Services {
7
+ build: Build;
8
+ }
5
9
  interface Loaders {
6
10
  css: Loader;
7
11
  csv: Loader;
package/package.json CHANGED
@@ -1,19 +1,19 @@
1
1
  {
2
2
  "name": "@roots/bud-build",
3
- "version": "6.13.1",
3
+ "version": "6.14.1",
4
4
  "description": "bud.js core module",
5
5
  "engines": {
6
6
  "node": ">=16"
7
7
  },
8
8
  "contributors": [
9
9
  {
10
- "name": "Kelly Mears",
11
10
  "email": "developers@tinypixel.dev",
11
+ "name": "Kelly Mears",
12
12
  "url": "https://github.com/kellymears"
13
13
  },
14
14
  {
15
- "name": "Ben Word",
16
15
  "email": "ben@benword.com",
16
+ "name": "Ben Word",
17
17
  "url": "https://github.com/retlehs"
18
18
  },
19
19
  {
@@ -21,8 +21,8 @@
21
21
  "url": "https://github.com/QWp6t"
22
22
  },
23
23
  {
24
- "name": "Brandon",
25
24
  "email": "brandon@tendency.me",
25
+ "name": "Brandon",
26
26
  "url": "https://github.com/Log1x"
27
27
  }
28
28
  ],
@@ -85,15 +85,15 @@
85
85
  "types": "./lib/index.d.ts",
86
86
  "module": "./lib/index.js",
87
87
  "devDependencies": {
88
- "@roots/bud-api": "6.13.1",
89
- "@roots/bud-hooks": "6.13.1",
88
+ "@roots/bud-api": "6.14.1",
89
+ "@roots/bud-hooks": "6.14.1",
90
90
  "@skypack/package-check": "0.2.2",
91
- "@types/node": "18.16.16"
91
+ "@types/node": "18.16.18"
92
92
  },
93
93
  "dependencies": {
94
- "@roots/bud-framework": "6.13.1",
95
- "@roots/bud-support": "6.13.1",
96
- "tslib": "2.5.3"
94
+ "@roots/bud-framework": "6.14.1",
95
+ "@roots/bud-support": "6.14.1",
96
+ "tslib": "2.6.0"
97
97
  },
98
98
  "volta": {
99
99
  "extends": "../../../package.json"
@@ -1,6 +1,13 @@
1
1
  import type {Factory} from './index.js'
2
2
 
3
- export const experiments: Factory<`experiments`> = async ({hooks}) =>
3
+ export const experiments: Factory<`experiments`> = async ({
4
+ hooks,
5
+ isDevelopment,
6
+ }) =>
4
7
  hooks.filter(`build.experiments`, {
5
8
  backCompat: false,
9
+ lazyCompilation: isDevelopment
10
+ ? {entries: false, imports: true}
11
+ : false,
12
+ topLevelAwait: true,
6
13
  })
@@ -8,7 +8,7 @@ describe(`bud.build.config`, function () {
8
8
  let build: Build
9
9
 
10
10
  beforeEach(async () => {
11
- bud = await factory()
11
+ bud = await factory({cache: `filesystem`})
12
12
  build = new Build(() => bud)
13
13
  await build.register(bud)
14
14
  await build.make()
@@ -28,7 +28,7 @@ describe(`bud.build.config`, function () {
28
28
 
29
29
  expect(cache.type).toStrictEqual(`filesystem`)
30
30
 
31
- expect(cache.version).toStrictEqual(expect.any(String))
31
+ expect(cache.version).toStrictEqual(undefined)
32
32
  })
33
33
 
34
34
  it(`should have expected context default`, async () => {
@@ -1,4 +1,4 @@
1
- import logger from '@roots/bud-support/utilities/logger'
1
+ import logger from '@roots/bud-support/logger'
2
2
 
3
3
  import type {Factory} from './index.js'
4
4
 
@@ -2,7 +2,6 @@ import type {Factory} from '../index.js'
2
2
 
3
3
  import {isMjs} from '../../helpers/isMjs.js'
4
4
  import {assetModuleFilename} from './assetModuleFilename.js'
5
- import {chunkFilename} from './chunkFilename.js'
6
5
  import {filename} from './filename.js'
7
6
 
8
7
  export const output: Factory<`output`> = async ({
@@ -13,17 +12,23 @@ export const output: Factory<`output`> = async ({
13
12
  }) =>
14
13
  filter(`build.output`, {
15
14
  assetModuleFilename: assetModuleFilename({filter, relPath}),
16
- chunkFilename: chunkFilename({filter, relPath}),
15
+ /**
16
+ * This should be kept undefined as documented here:
17
+ * {@see https://webpack.js.org/plugins/split-chunks-plugin/#splitchunkscachegroupscachegroupfilename}
18
+ */
19
+ // chunkFilename: chunkFilename({filter, relPath}),
17
20
  clean: filter(`build.output.clean`, isProduction),
18
21
  environment: filter(`build.output.environment`, undefined),
19
22
  filename: filename({filter, relPath}),
23
+ hashFunction: filter(`build.output.hashFunction`, `xxhash64`),
24
+ iife: filter(`build.output.iife`, undefined),
20
25
  module: filter(`build.output.module`, false),
21
26
  path: filter(`build.output.path`, path(`@dist`)),
22
27
  pathinfo: filter(`build.output.pathinfo`, false),
23
28
  publicPath: filter(`build.output.publicPath`, `auto`),
24
29
  scriptType: filter(
25
30
  `build.output.scriptType`,
26
- isMjs(filter) ? `module` : false,
31
+ isMjs(filter) ? `module` : `text/javascript`,
27
32
  ),
28
33
  uniqueName: filter(`build.output.uniqueName`, `@roots/bud`),
29
34
  })
@@ -2,5 +2,15 @@ import {cpus} from 'node:os'
2
2
 
3
3
  import type {Factory} from './index.js'
4
4
 
5
- export const parallelism: Factory<`parallelism`> = async ({hooks}) =>
6
- hooks.filter(`build.parallelism`, 10 * Math.max(cpus().length - 1, 1))
5
+ export const parallelism: Factory<`parallelism`> = async ({
6
+ hooks,
7
+ root,
8
+ }) => {
9
+ const factor = 10
10
+ const procs = Math.min(cpus().length - 1, 1)
11
+ const comps = root.hasChildren
12
+ ? Math.min(Object.keys(root.children).length)
13
+ : 1
14
+
15
+ return hooks.filter(`build.parallelism`, (procs * factor) / comps)
16
+ }
@@ -1,3 +1,5 @@
1
+ import isString from '@roots/bud-support/lodash/isString'
2
+
1
3
  import type {Factory} from './index.js'
2
4
 
3
5
  export const resolve: Factory<`resolve`> = async bud => {
@@ -6,6 +8,7 @@ export const resolve: Factory<`resolve`> = async bud => {
6
8
  [`@src`]: bud.path(`@src`),
7
9
  ...(await bud.hooks.filterAsync(`build.resolve.alias`, {})),
8
10
  },
11
+
9
12
  extensionAlias: await bud.hooks.filterAsync(
10
13
  `build.resolve.extensionAlias`,
11
14
  {
@@ -13,16 +16,22 @@ export const resolve: Factory<`resolve`> = async bud => {
13
16
  [`.mjs`]: [`.mts`, `.mtx`, `.mjs`],
14
17
  },
15
18
  ),
19
+
16
20
  extensions: Array.from(
17
21
  bud.hooks.filter(
18
22
  `build.resolve.extensions`,
19
23
  new Set([`.js`, `.mjs`, `.jsx`, `.css`]),
20
24
  ),
21
25
  ),
22
- modules: await bud.hooks.filterAsync(`build.resolve.modules`, [
23
- bud.hooks.filter(`location.@src`),
24
- bud.hooks.filter(`location.@modules`),
25
- ]),
26
+
27
+ modules: await bud.hooks.filterAsync(
28
+ `build.resolve.modules`,
29
+ [
30
+ bud.hooks.filter(`location.@src`),
31
+ bud.hooks.filter(`location.@modules`),
32
+ ].filter(v => isString(v) && v.length > 0),
33
+ ),
34
+
26
35
  /**
27
36
  * Leave `undefined` to use webpack default (true in dev, false in production)
28
37
  */
@@ -1,6 +1,23 @@
1
1
  import type {Factory} from './index.js'
2
2
 
3
- export const resolveLoader: Factory<`resolveLoader`> = async ({hooks}) =>
3
+ export const resolveLoader: Factory<`resolveLoader`> = async ({
4
+ hooks,
5
+ module,
6
+ }) =>
4
7
  hooks.filter(`build.resolveLoader`, {
5
- alias: hooks.filter(`build.resolveLoader.alias`, {}),
8
+ alias: hooks.filter(`build.resolveLoader.alias`, {
9
+ 'css-loader': await module.resolve(`@roots/bud-support/css-loader`),
10
+ 'file-loader': await module.resolve(
11
+ `@roots/bud-support/file-loader`,
12
+ ),
13
+ 'html-loader': await module.resolve(
14
+ `@roots/bud-support/html-loader`,
15
+ ),
16
+ json5: await module.resolve(`@roots/bud-support/json5`),
17
+ 'mini-svg-data-uri': await module.resolve(`mini-svg-data-uri`),
18
+ 'style-loader': await module.resolve(
19
+ `@roots/bud-support/style-loader`,
20
+ ),
21
+ toml: await module.resolve(`@roots/bud-support/toml`),
22
+ }),
6
23
  })
@@ -7,7 +7,10 @@ export const stats: Factory<`stats`> = async app =>
7
7
  ? {
8
8
  all: false,
9
9
  assets: true,
10
+ assetsSort: `size`,
11
+ builtAt: false,
10
12
  children: false,
13
+ chunks: false,
11
14
  entrypoints: true,
12
15
  errors: true,
13
16
  errorsCount: true,
package/src/item/index.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import type {Bud, Loaders} from '@roots/bud-framework'
2
2
  import type * as Build from '@roots/bud-framework/services/build'
3
3
 
4
+ import {basename} from 'path'
5
+
4
6
  import {bind} from '@roots/bud-support/decorators/bind'
5
7
  import isString from '@roots/bud-support/lodash/isString'
6
- import {basename} from 'path'
7
8
 
8
9
  import {Loader} from '../loader/index.js'
9
10
  import Base from '../shared/base.js'
package/src/service.ts CHANGED
@@ -1,6 +1,6 @@
1
+ import type {Bud, Build as BudBuild} from '@roots/bud-framework'
1
2
  import type {Items, Loaders, Rules} from '@roots/bud-framework'
2
3
  import type {Configuration} from '@roots/bud-framework/config'
3
- import type * as Base from '@roots/bud-framework/services/build'
4
4
 
5
5
  import {Service} from '@roots/bud-framework/service'
6
6
  import {bind} from '@roots/bud-support/decorators/bind'
@@ -18,7 +18,7 @@ import {Rule} from './rule/index.js'
18
18
  /**
19
19
  * Webpack configuration builder class
20
20
  */
21
- export class Build extends Service implements Base.Service {
21
+ export class Build extends Service implements BudBuild {
22
22
  /**
23
23
  * Built config object
24
24
  */
@@ -27,26 +27,28 @@ export class Build extends Service implements Base.Service {
27
27
  /**
28
28
  * Registered items
29
29
  */
30
- public items: Items = {} as Items
30
+ public declare items: Items
31
31
 
32
32
  /**
33
33
  * Registered loaders
34
34
  */
35
- public loaders: Loaders = {} as Loaders
35
+ public declare loaders: Loaders
36
36
 
37
37
  /**
38
- * Service register event
39
- *
40
- * @remarks
41
- * `loaders`, `items`, and `rules` are instantiated dumbly
42
- * because it is painful to think about how to map the typings..
38
+ * {@link BudBuild.register}
43
39
  */
44
- public override register = register.bind(this)
40
+ public override register? = register.bind(this)
45
41
 
46
42
  /**
47
43
  * Registered rules
48
44
  */
49
- public rules: Rules = {} as Rules
45
+ public declare rules: Rules
46
+
47
+ public override async bootstrap?(app: Bud) {
48
+ this.items = {} as Items
49
+ this.loaders = {} as Loaders
50
+ this.rules = {} as Rules
51
+ }
50
52
 
51
53
  /**
52
54
  * Get item
package/src/types.ts CHANGED
@@ -1,8 +1,14 @@
1
- import type {Item} from './item/index.js'
2
- import type {Loader} from './loader/index.js'
3
- import type {Rule} from './rule/index.js'
1
+ import type {Item} from '@roots/bud-build/item'
2
+ import type {Loader} from '@roots/bud-build/loader'
3
+ import type {Rule} from '@roots/bud-build/rule'
4
+
5
+ import type {Build} from './service.js'
4
6
 
5
7
  declare module '@roots/bud-framework' {
8
+ interface Services {
9
+ build: Build
10
+ }
11
+
6
12
  interface Loaders {
7
13
  css: Loader
8
14
  csv: Loader
@@ -1,7 +0,0 @@
1
- import type { Bud } from '@roots/bud-framework';
2
- interface Props {
3
- filter: Bud[`hooks`][`filter`];
4
- relPath: Bud[`relPath`];
5
- }
6
- export declare const chunkFilename: ({ filter, relPath }: Props) => string | ((pathData: import("webpack").PathData, assetInfo?: import("webpack").AssetInfo) => string);
7
- export {};
@@ -1,3 +0,0 @@
1
- import { join } from 'node:path';
2
- import { scriptExtension } from '../../helpers/scriptExtension.js';
3
- export const chunkFilename = ({ filter, relPath }) => filter(`build.output.chunkFilename`, join(`js`, `dynamic`, relPath(`@name.chunk`)).concat(scriptExtension(filter, `.mjs`, `.js`)));
@@ -1,18 +0,0 @@
1
- import type {Bud} from '@roots/bud-framework'
2
-
3
- import {join} from 'node:path'
4
-
5
- import {scriptExtension} from '../../helpers/scriptExtension.js'
6
-
7
- interface Props {
8
- filter: Bud[`hooks`][`filter`]
9
- relPath: Bud[`relPath`]
10
- }
11
-
12
- export const chunkFilename = ({filter, relPath}: Props) =>
13
- filter(
14
- `build.output.chunkFilename`,
15
- join(`js`, `dynamic`, relPath(`@name.chunk`)).concat(
16
- scriptExtension(filter, `.mjs`, `.js`),
17
- ),
18
- )