Skip to content

Commit

Permalink
🏎️ performance: optimize build performance (#2280)
Browse files Browse the repository at this point in the history
- use loader resolution aliases
- tweaks to default `build.*` values
- babel done on `register`

## Type of change

**PATCH: backwards compatible change**
  • Loading branch information
kellymears authored May 19, 2023
1 parent d98ecde commit 360aa61
Show file tree
Hide file tree
Showing 24 changed files with 286 additions and 158 deletions.
72 changes: 40 additions & 32 deletions sources/@roots/bud-babel/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
label,
} from '@roots/bud-framework/extension/decorators'
import {InputError} from '@roots/bud-support/errors'
import isString from '@roots/bud-support/lodash/isString'
import isUndefined from '@roots/bud-support/lodash/isUndefined'

import type {LoaderOptions, Registry} from './types.js'
Expand Down Expand Up @@ -105,34 +106,55 @@ export default class BabelExtension extends Extension {
configFile: false,
}

return this.overridenByProjectConfigFile
? {
...baseOptions,
...this.configFileOptions,
}
: {
...baseOptions,
presets: Object.values(this.presets),
plugins: Object.values(this.plugins),
env: this.env,
root: this.root,
targets:
this.app.context.files[`package.json`].module.browserslist ??
`defaults`,
}
if (this.overridenByProjectConfigFile) {
return {
...baseOptions,
...this.configFileOptions,
}
}

return {
...baseOptions,
presets: Object.values(this.presets),
plugins: Object.values(this.plugins),
env: this.env,
root: this.root,
targets:
this.app.context.files[`package.json`].module.browserslist ??
`defaults`,
}
}

/**
* {@link Extension.register}
*/
@bind
public override async register() {
public override async register({build, hooks}: Bud) {
const loader = await this.resolve(`babel-loader`, import.meta.url)
if (!loader) throw new Error(`babel-loader not found`)
hooks.on(`build.resolveLoader.alias`, (alias = {}) => ({
...alias,
[`babel-loader`]: loader,
}))

if (this.overridenByProjectConfigFile) {
this.logger.log(
`Babel configuration is being overridden by project configuration file.`,
)

this.configFileOptions =
this.configFile.module.default ?? this.configFile.module

hooks.on(`build.cache.buildDependencies`, paths => {
if (isString(this.configFile)) {
paths.babel = [this.configFile]
this.logger.success(
`babel config added to webpack build dependencies`,
)
}
return paths
})

return
}

Expand All @@ -146,31 +168,17 @@ export default class BabelExtension extends Extension {
`@babel/plugin-transform-runtime`,
import.meta.url,
)

if (transformRuntime)
this.setPlugin(`@babel/plugin-transform-runtime`, [
transformRuntime,
{helpers: false},
])
}

/**
* {@link Extension.configAfter}
*/
@bind
public override async configAfter(bud: Bud) {
const loader = await this.resolve(`babel-loader`, import.meta.url)
if (!loader) return this.logger.error(`Babel loader not found`)

bud.build.setLoader(`babel`, loader).setItem(`babel`, {
build.setLoader(`babel`, `babel-loader`).setItem(`babel`, {
loader: `babel`,
options: () => this.loaderOptions,
})

bud.build.rules.js.setUse((items = []) => [
bud.build.items.babel,
...items,
])
build.rules.js.setUse((items = []) => [`babel`, ...items])
}

/**
Expand Down
4 changes: 0 additions & 4 deletions sources/@roots/bud-babel/test/extension.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ describe(`@roots/bud-babel`, () => {
expect(BabelInstance.register).toBeDefined()
})

it(`should have configAfter method`, async () => {
expect(BabelInstance.configAfter).toBeDefined()
})

it(`config class shoudl have setPlugins`, async () => {
expect(BabelInstance.setPlugins).toBeInstanceOf(Function)
})
Expand Down
3 changes: 2 additions & 1 deletion sources/@roots/bud-build/src/config/externalsType.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type {Factory} from './index.js'

export const externalsType: Factory<`externalsType`> = async app => `var`
export const externalsType: Factory<`externalsType`> = async app =>
undefined
2 changes: 1 addition & 1 deletion sources/@roots/bud-build/src/config/performance.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type {Factory} from './index.js'

export const performance: Factory<`performance`> = async ({hooks}) =>
hooks.filter(`build.performance`, {hints: false})
hooks.filter(`build.performance`, false)
7 changes: 5 additions & 2 deletions sources/@roots/bud-build/src/config/profile.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import type {Factory} from './index.js'

export const profile: Factory<`profile`> = async app =>
app.hooks.filter(`build.profile`, undefined)
export const profile: Factory<`profile`> = async bud =>
bud.hooks.filter(
`build.profile`,
bud.isCLI() && bud.context.args[`debug`],
)
5 changes: 4 additions & 1 deletion sources/@roots/bud-build/src/config/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ export const resolve: Factory<`resolve`> = async bud => {
bud.hooks.filter(`location.@src`),
bud.hooks.filter(`location.@modules`),
]),
unsafeCache: bud.hooks.filter(`build.module.unsafeCache`, false),
/**
* Leave `undefined` to use webpack default (true in dev, false in production)
*/
unsafeCache: bud.hooks.filter(`build.module.unsafeCache`, undefined),
})
}
6 changes: 3 additions & 3 deletions sources/@roots/bud-build/src/config/resolveLoader.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type {Factory} from './index.js'

export const resolveLoader: Factory<`resolveLoader`> = async bud =>
bud.hooks.filter(`build.resolveLoader`, {
alias: {},
export const resolveLoader: Factory<`resolveLoader`> = async ({hooks}) =>
hooks.filter(`build.resolveLoader`, {
alias: hooks.filter(`build.resolveLoader.alias`, {}),
})
25 changes: 21 additions & 4 deletions sources/@roots/bud-build/src/config/snapshot.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,25 @@
import type {Factory} from './index.js'

export const snapshot: Factory<`snapshot`> = async app =>
app.hooks.filter(`build.snapshot`, {
managedPaths: app.hooks.filter(`build.snapshot.managedPaths`, [
...new Set([app.path(`@modules`)]),
export const snapshot: Factory<`snapshot`> = async ({env, hooks, path}) =>
hooks.filter(`build.snapshot`, {
immutablePaths: hooks.filter(`build.snapshot.immutablePaths`, []),
managedPaths: hooks.filter(`build.snapshot.managedPaths`, [
...new Set([path(`@modules`)]),
]),
buildDependencies: hooks.filter(
`build.snapshot.buildDependencies`,
env.isTrue(`CI`) ? {hash: true} : {timestamp: true},
),
module: hooks.filter(
`build.snapshot.module`,
env.isTrue(`CI`) ? {hash: true} : {timestamp: true},
),
resolve: hooks.filter(
`build.snapshot.resolve`,
env.isTrue(`CI`) ? {hash: true} : {timestamp: true},
),
resolveBuildDependencies: hooks.filter(
`build.snapshot.resolveBuildDependencies`,
env.isTrue(`CI`) ? {hash: true} : {timestamp: true},
),
})
19 changes: 12 additions & 7 deletions sources/@roots/bud-esbuild/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,18 @@ export default class BudEsbuild extends Extension<Options> {
* {@link Extension.register}
*/
@bind
public override async register(bud: Bud) {
bud.hooks
.on(`build.resolve.extensions`, ext => ext.add(`.ts`).add(`.tsx`))
.build.setLoader(
`esbuild`,
await this.resolve(`esbuild-loader`, import.meta.url),
)
public override async register({build, hooks}: Bud) {
const loader = await this.resolve(`esbuild-loader`, import.meta.url)
if (!loader) return this.logger.error(`Esbuild loader not found`)

hooks.on(`build.resolve.extensions`, ext => ext.add(`.ts`).add(`.tsx`))
hooks.on(`build.resolveLoader.alias`, (aliases = {}) => ({
...aliases,
[`esbuild-loader`]: loader,
}))

build
.setLoader(`esbuild`, `esbuild-loader`)
.setItem(`esbuild-js`, {
loader: `esbuild`,
options: () => this.options.js,
Expand Down
1 change: 0 additions & 1 deletion sources/@roots/bud-eslint/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ export class BudEslint extends Extension<Options, EslintPlugin> {
this.set(`eslintPath`, await this.resolve(`eslint`, import.meta.url))

if (!bud.context.files) return

const config = Object.values(bud.context.files).find(
({file, name}) => file && name.includes(`eslint`),
)
Expand Down
7 changes: 6 additions & 1 deletion sources/@roots/bud-framework/src/types/registry/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,14 @@ export interface Sync {
'resolve.extensions': Set<string>
'resolve.extensionAlias': Configuration['resolve']['extensionAlias']
resolveLoader: Configuration['resolveLoader']
'resolveLoader.alias': Configuration[`resolveLoader`][`alias`]
snapshot: Configuration[`snapshot`]
'snapshot.buildDependencies': Configuration[`snapshot`][`buildDependencies`]
'snapshot.immutablePaths': Configuration[`snapshot`][`immutablePaths`]
'snapshot.managedPaths': Configuration[`snapshot`][`managedPaths`]

'snapshot.module': Configuration[`snapshot`][`module`]
'snapshot.resolveBuildDependencies': Configuration[`snapshot`][`resolveBuildDependencies`]
'snapshot.resolve': Configuration[`snapshot`][`resolve`]
stats: StatsOptions
'stats.preset': string
target: Configuration['target']
Expand Down
40 changes: 20 additions & 20 deletions sources/@roots/bud-mdx/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,27 @@ export class BudMDX extends Extension {
* {@link Extension.register}
*/
@bind
public override async register(bud: Bud) {
bud.hooks.on(`build.resolve.extensions`, ext =>
ext.add(`.md`).add(`.mdx`),
)
public override async register({build, hooks}: Bud) {
const loader = await this.resolve(`@mdx-js/loader`, import.meta.url)
if (!loader) return this.logger.error(`MDX loader not found`)

bud.build
.setLoader(
`mdx`,
await this.resolve(`@mdx-js/loader`, import.meta.url),
)
.setItem(`mdx`, {
loader: `mdx`,
options: () => ({
rehypePlugins: this.get(`rehypePlugins`)
? Object.values(this.get(`rehypePlugins`))
: [],
remarkPlugins: this.get(`remarkPlugins`)
? Object.values(this.get(`remarkPlugins`))
: [],
}),
})
hooks.on(`build.resolve.extensions`, ext => ext.add(`.md`).add(`.mdx`))
hooks.on(`build.resolveLoader.alias`, (aliases = {}) => ({
...aliases,
[`@mdx-js/loader`]: loader,
}))

build.setLoader(`mdx`, `@mdx-js/loader`).setItem(`mdx`, {
loader: `mdx`,
options: () => ({
rehypePlugins: this.get(`rehypePlugins`)
? Object.values(this.get(`rehypePlugins`))
: [],
remarkPlugins: this.get(`remarkPlugins`)
? Object.values(this.get(`remarkPlugins`))
: [],
}),
})
}

/**
Expand Down
67 changes: 49 additions & 18 deletions sources/@roots/bud-postcss/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from '@roots/bud-framework/extension/decorators'
import {deprecated} from '@roots/bud-support/decorators/deprecated'
import {InputError} from '@roots/bud-support/errors'
import isString from '@roots/bud-support/lodash/isString'
import isUndefined from '@roots/bud-support/lodash/isUndefined'
import type {Plugin, Processor} from 'postcss'

Expand Down Expand Up @@ -56,7 +57,35 @@ export class BudPostCss extends Extension<Options> {
* {@link Extension.register}
*/
@bind
public override async register({build, context}: Bud): Promise<void> {
public override async register({
build,
context,
hooks,
}: Bud): Promise<void> {
const loader = await this.resolve(`postcss-loader`, import.meta.url)
if (!loader) throw new Error(`postcss-loader not found`)

hooks.on(`build.resolveLoader.alias`, (aliases = {}) => ({
...aliases,
[`postcss-loader`]: loader,
}))

build
.setLoader(
`postcss`,
await this.resolve(`postcss-loader`, import.meta.url),
)
.setItem(`postcss`, {
loader: `postcss`,
options: () => ({
postcssOptions: this.configFileOptions ?? this.postcssOptions,
sourceMap: this.get(`sourceMap`),
}),
})

build.rules.css.setUse((items = []) => [...items, `postcss`])
build.rules.cssModule?.setUse((items = []) => [...items, `postcss`])

if (
!context.files ||
!Object.values(context.files).some(
Expand Down Expand Up @@ -86,26 +115,20 @@ export class BudPostCss extends Extension<Options> {
`PostCSS configuration is being overridden by project configuration file.`,
)
this.set(`postcssOptions.config`, true)
this.configFileOptions = Object.values(this.app.context.files).find(
file => file?.name?.includes(`postcss`) && file?.module,
)?.module
}

build
.setLoader(
`postcss`,
await this.resolve(`postcss-loader`, import.meta.url),
const config = Object.values(context.files).find(
file => file?.name?.includes(`postcss`) && file?.module,
)
.setItem(`postcss`, {
loader: `postcss`,
options: () => ({
postcssOptions: this.configFileOptions ?? this.postcssOptions,
sourceMap: this.get(`sourceMap`),
}),
})

build.rules.css.setUse((items = []) => [...items, `postcss`])
build.rules.cssModule?.setUse((items = []) => [...items, `postcss`])
if (isString(config.path))
hooks.on(`build.cache.buildDependencies`, paths => ({
...paths,
postcss: [config.path],
}))

if (!isUndefined(config.module))
this.configFileOptions = config.module.default ?? config.module
}
}

/**
Expand Down Expand Up @@ -141,6 +164,14 @@ export class BudPostCss extends Extension<Options> {
return this
}

/**
* Get plugins
*/
@bind
public getPlugins() {
return this.get(`plugins`) as InputRecords
}

/**
* Set plugins
*/
Expand Down
Loading

0 comments on commit 360aa61

Please sign in to comment.