diff --git a/sources/@roots/bud-babel/src/extension.ts b/sources/@roots/bud-babel/src/extension.ts index ba071985fe..fdcbb23c2d 100644 --- a/sources/@roots/bud-babel/src/extension.ts +++ b/sources/@roots/bud-babel/src/extension.ts @@ -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' @@ -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 } @@ -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]) } /** diff --git a/sources/@roots/bud-babel/test/extension.test.ts b/sources/@roots/bud-babel/test/extension.test.ts index e7ca15cd8a..8013f78a3f 100644 --- a/sources/@roots/bud-babel/test/extension.test.ts +++ b/sources/@roots/bud-babel/test/extension.test.ts @@ -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) }) diff --git a/sources/@roots/bud-build/src/config/externalsType.ts b/sources/@roots/bud-build/src/config/externalsType.ts index e104f2b3bd..54fceef50c 100644 --- a/sources/@roots/bud-build/src/config/externalsType.ts +++ b/sources/@roots/bud-build/src/config/externalsType.ts @@ -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 diff --git a/sources/@roots/bud-build/src/config/performance.ts b/sources/@roots/bud-build/src/config/performance.ts index bbfeb616d6..804cc35e47 100644 --- a/sources/@roots/bud-build/src/config/performance.ts +++ b/sources/@roots/bud-build/src/config/performance.ts @@ -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) diff --git a/sources/@roots/bud-build/src/config/profile.ts b/sources/@roots/bud-build/src/config/profile.ts index 375786c1a3..3150c11b12 100644 --- a/sources/@roots/bud-build/src/config/profile.ts +++ b/sources/@roots/bud-build/src/config/profile.ts @@ -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`], + ) diff --git a/sources/@roots/bud-build/src/config/resolve.ts b/sources/@roots/bud-build/src/config/resolve.ts index ebea670fc6..a0420f2cba 100644 --- a/sources/@roots/bud-build/src/config/resolve.ts +++ b/sources/@roots/bud-build/src/config/resolve.ts @@ -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), }) } diff --git a/sources/@roots/bud-build/src/config/resolveLoader.ts b/sources/@roots/bud-build/src/config/resolveLoader.ts index bbfadd346a..dfbc4a994f 100644 --- a/sources/@roots/bud-build/src/config/resolveLoader.ts +++ b/sources/@roots/bud-build/src/config/resolveLoader.ts @@ -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`, {}), }) diff --git a/sources/@roots/bud-build/src/config/snapshot.ts b/sources/@roots/bud-build/src/config/snapshot.ts index a3edfec732..f05945b1af 100644 --- a/sources/@roots/bud-build/src/config/snapshot.ts +++ b/sources/@roots/bud-build/src/config/snapshot.ts @@ -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}, + ), }) diff --git a/sources/@roots/bud-esbuild/src/extension.ts b/sources/@roots/bud-esbuild/src/extension.ts index fdfdbb6672..28fa1b14d0 100644 --- a/sources/@roots/bud-esbuild/src/extension.ts +++ b/sources/@roots/bud-esbuild/src/extension.ts @@ -76,13 +76,18 @@ export default class BudEsbuild extends Extension { * {@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, diff --git a/sources/@roots/bud-eslint/src/extension.ts b/sources/@roots/bud-eslint/src/extension.ts index c0d2cd2ed0..362afb5025 100644 --- a/sources/@roots/bud-eslint/src/extension.ts +++ b/sources/@roots/bud-eslint/src/extension.ts @@ -45,7 +45,6 @@ export class BudEslint extends Extension { 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`), ) diff --git a/sources/@roots/bud-framework/src/types/registry/build.ts b/sources/@roots/bud-framework/src/types/registry/build.ts index 26618640a9..bfdaa0c83b 100644 --- a/sources/@roots/bud-framework/src/types/registry/build.ts +++ b/sources/@roots/bud-framework/src/types/registry/build.ts @@ -82,9 +82,14 @@ export interface Sync { 'resolve.extensions': Set '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'] diff --git a/sources/@roots/bud-mdx/src/extension.ts b/sources/@roots/bud-mdx/src/extension.ts index d26ba3c55f..e34d899d90 100644 --- a/sources/@roots/bud-mdx/src/extension.ts +++ b/sources/@roots/bud-mdx/src/extension.ts @@ -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`)) + : [], + }), + }) } /** diff --git a/sources/@roots/bud-postcss/src/extension.ts b/sources/@roots/bud-postcss/src/extension.ts index ccfc69b07d..77d437f166 100644 --- a/sources/@roots/bud-postcss/src/extension.ts +++ b/sources/@roots/bud-postcss/src/extension.ts @@ -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' @@ -56,7 +57,35 @@ export class BudPostCss extends Extension { * {@link Extension.register} */ @bind - public override async register({build, context}: Bud): Promise { + public override async register({ + build, + context, + hooks, + }: Bud): Promise { + 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( @@ -86,26 +115,20 @@ export class BudPostCss extends Extension { `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 + } } /** @@ -141,6 +164,14 @@ export class BudPostCss extends Extension { return this } + /** + * Get plugins + */ + @bind + public getPlugins() { + return this.get(`plugins`) as InputRecords + } + /** * Set plugins */ diff --git a/sources/@roots/bud-postcss/src/types.ts b/sources/@roots/bud-postcss/src/types.ts index e49f184439..43f0add7ab 100644 --- a/sources/@roots/bud-postcss/src/types.ts +++ b/sources/@roots/bud-postcss/src/types.ts @@ -10,11 +10,12 @@ import type {BudPostCss} from './extension.js' interface PublicPostCssApi extends PublicExtensionApi { postcssOptions: BudPostCss[`postcssOptions`] getPlugin: BudPostCss[`getPlugin`] + setPlugin: BudPostCss[`setPlugin`] getPluginPath: BudPostCss[`getPluginPath`] setPluginPath: BudPostCss[`setPluginPath`] getPluginOptions: BudPostCss[`getPluginOptions`] setPluginOptions: BudPostCss[`setPluginOptions`] - setPlugin: BudPostCss[`setPlugin`] + getPlugins: BudPostCss[`getPlugins`] setPlugins: BudPostCss[`setPlugins`] unsetPlugin: BudPostCss[`unsetPlugin`] use: BudPostCss[`use`] diff --git a/sources/@roots/bud-postcss/test/extension.test.ts b/sources/@roots/bud-postcss/test/extension.test.ts index 6caafb1d3e..7cbbd1f7fe 100644 --- a/sources/@roots/bud-postcss/test/extension.test.ts +++ b/sources/@roots/bud-postcss/test/extension.test.ts @@ -13,6 +13,12 @@ describe(`@roots/bud-postcss`, () => { expect(bud.postcss.label).toBe(`@roots/bud-postcss`) }) + it(`getPlugins`, async () => { + const bud = await factory() + await bud.extensions.add(BudPostCss) + expect(bud.postcss.getPlugins()).toBe(bud.postcss.get(`plugins`)) + }) + it(`setPlugins from obj`, async () => { const bud = await factory() await bud.extensions.add(BudPostCss) diff --git a/sources/@roots/bud-preset-wordpress/src/extension.ts b/sources/@roots/bud-preset-wordpress/src/extension.ts index 9b415bdc28..fe930b47d7 100644 --- a/sources/@roots/bud-preset-wordpress/src/extension.ts +++ b/sources/@roots/bud-preset-wordpress/src/extension.ts @@ -48,9 +48,24 @@ export default class BudPresetWordPress extends Extension { /** * {@link Extension.buildBefore} */ - public override async buildBefore({build}, options: Options) { + public override async buildBefore({build, hooks}, options: Options) { + /** Bail if hmr option is false */ if (!options.hmr) return + /** Source loader */ + const loader = await this.resolve( + `@roots/wordpress-hmr/loader`, + import.meta.url, + ) + /** Bail if unresolvable */ + if (!loader) return this.logger.error(`HMR loader not found`) + + /** Set loader alias */ + hooks.on(`build.resolveLoader.alias`, (aliases = {}) => ({ + ...aliases, + [`@roots/wordpress-hmr/loader`]: loader, + })) + build .setLoader( `@roots/wordpress-hmr/loader`, diff --git a/sources/@roots/bud-sass/src/extension.ts b/sources/@roots/bud-sass/src/extension.ts index 5d57988326..e25516bf0e 100644 --- a/sources/@roots/bud-sass/src/extension.ts +++ b/sources/@roots/bud-sass/src/extension.ts @@ -25,15 +25,32 @@ export class BudSass extends Extension { * {@link Extension.register} */ @bind - public override async register(bud: Bud) { + public override async register({build, hooks}: Bud) { + /** Source loader */ + const loader = await this.resolve(`sass-loader`, import.meta.url) + if (!loader) return this.logger.error(`sass-loader not found`) + + /** Source sass implementation */ const implementation = await this.import(`sass`) + if (!implementation) return this.logger.error(`sass not found`) + + /** Set options */ this.setOptions({implementation, sourceMap: true}) - bud.build - .setLoader( - `sass-loader`, - await this.resolve(`sass-loader`, import.meta.url), - ) + /** Set loader alias */ + hooks.on(`build.resolveLoader.alias`, (aliases = {}) => ({ + ...aliases, + [`sass-loader`]: loader, + })) + + /** Resolve .scss and .sass extensions */ + hooks.on(`build.resolve.extensions`, ext => + ext.add(`.scss`).add(`.sass`), + ) + + /** Setup rule */ + build + .setLoader(`sass-loader`, loader) .setItem(`sass`, { ident: `sass`, loader: `sass-loader`, @@ -43,10 +60,6 @@ export class BudSass extends Extension { test: (app: Bud) => app.hooks.filter(`pattern.sass`), include: [app => app.path(`@src`)], }) - - bud.hooks.on(`build.resolve.extensions`, ext => - ext.add(`.scss`).add(`.sass`), - ) } /** @@ -60,11 +73,11 @@ export class BudSass extends Extension { bud.build.rules.sass.setUse(() => [ - bud.build.items.precss, - bud.build.items.css, - bud.build.items.postcss, - bud.build.items.resolveUrl, - bud.build.items.sass, + bud.build.items[`precss`], + bud.build.items[`css`], + bud.build.items[`postcss`], + bud.build.items[`resolve-url`], + bud.build.items[`sass`], ].filter(Boolean), ) } diff --git a/sources/@roots/bud-sass/src/resolve-url/extension.ts b/sources/@roots/bud-sass/src/resolve-url/extension.ts index bca5a82db0..d6662633bd 100644 --- a/sources/@roots/bud-sass/src/resolve-url/extension.ts +++ b/sources/@roots/bud-sass/src/resolve-url/extension.ts @@ -10,15 +10,24 @@ export class BudResolveUrl extends Extension { /** * {@link Extension.register} */ - public override async register(bud: Bud) { - bud.build - .setLoader( - `resolveUrl`, - await this.resolve(`resolve-url-loader`, import.meta.url), - ) - .setItem(`resolveUrl`, { - loader: `resolveUrl`, - options: ({path}) => ({root: path(`@src`), sourceMap: true}), - }) + public override async register({build, hooks}: Bud) { + /** Source loader */ + const loader = await this.resolve( + `resolve-url-loader`, + import.meta.url, + ) + if (!loader) return this.logger.error(`resolve-url-loader not found`) + + /** Set loader alias */ + hooks.on(`build.resolveLoader.alias`, (aliases = {}) => ({ + ...aliases, + [`resolve-url-loader`]: loader, + })) + + /** Setup rule */ + build.setLoader(`resolve-url`, loader).setItem(`resolve-url`, { + loader: `resolve-url`, + options: ({path}) => ({root: path(`@src`), sourceMap: true}), + }) } } diff --git a/sources/@roots/bud-sass/src/types.ts b/sources/@roots/bud-sass/src/types.ts index 843639e3ad..c6d4dcc540 100644 --- a/sources/@roots/bud-sass/src/types.ts +++ b/sources/@roots/bud-sass/src/types.ts @@ -23,12 +23,12 @@ declare module '@roots/bud-framework' { } interface Loaders { - resolveUrl: Build.Loader + 'resolve-url': Build.Loader 'sass-loader': Build.Loader } interface Items { - resolveUrl: Build.Item + 'resolve-url': Build.Item sass: Build.Item } diff --git a/sources/@roots/bud-sass/test/resolveUrl.test.ts b/sources/@roots/bud-sass/test/resolve-url.test.ts similarity index 87% rename from sources/@roots/bud-sass/test/resolveUrl.test.ts rename to sources/@roots/bud-sass/test/resolve-url.test.ts index f69942ee98..78113c7663 100644 --- a/sources/@roots/bud-sass/test/resolveUrl.test.ts +++ b/sources/@roots/bud-sass/test/resolve-url.test.ts @@ -1,11 +1,11 @@ /* eslint-disable no-console */ import {beforeEach, describe, expect, it, vi} from 'vitest' -import {factory} from '@repo/test-kit/bud' +import {Bud, factory} from '@repo/test-kit/bud' import {BudResolveUrl} from '../src/resolve-url/extension.js' -describe(`@roots/bud-sass`, () => { - let bud - let extension +describe(`@roots/bud-sass/resolve-url`, () => { + let bud: Bud + let extension: BudResolveUrl beforeEach(async () => { vi.restoreAllMocks() @@ -49,9 +49,9 @@ describe(`@roots/bud-sass`, () => { } catch (e) {} expect(setItemSpy).toHaveBeenCalledWith( - `resolveUrl`, + `resolve-url`, expect.objectContaining({ - loader: `resolveUrl`, + loader: `resolve-url`, options: expect.any(Function), }), ) diff --git a/sources/@roots/bud-swc/src/extension/index.ts b/sources/@roots/bud-swc/src/extension/index.ts index 50e1a5cff0..874594757f 100644 --- a/sources/@roots/bud-swc/src/extension/index.ts +++ b/sources/@roots/bud-swc/src/extension/index.ts @@ -34,7 +34,6 @@ export default class BudSWC extends Extension { */ @bind public override async register({build, context, fs, hooks}: Bud) { - const swcPath = await this.resolve(`@swc/core`, import.meta.url) const loaderPath = await this.resolve(`swc-loader`, import.meta.url) if (context.files?.[`.swcrc`]) { @@ -43,17 +42,14 @@ export default class BudSWC extends Extension { ) } - hooks.on(`build.resolveLoader`, resolveLoader => ({ - ...(resolveLoader ?? {}), - alias: { - ...resolveLoader?.alias, - '@swc/core': swcPath, - 'swc-loader': loaderPath, - }, + /** set loader alias */ + hooks.on(`build.resolveLoader.alias`, (aliases = {}) => ({ + ...aliases, + 'swc-loader': loaderPath, })) - build.setLoader(`swc`, loaderPath).setItem(`swc`, { - loader: build.getLoader(`swc`), + build.setLoader(`swc`, `swc-loader`).setItem(`swc`, { + loader: `swc`, options: () => this.options, }) diff --git a/sources/@roots/bud-typescript/src/extension.ts b/sources/@roots/bud-typescript/src/extension.ts index 580614fee0..01fabda253 100644 --- a/sources/@roots/bud-typescript/src/extension.ts +++ b/sources/@roots/bud-typescript/src/extension.ts @@ -61,27 +61,30 @@ export default class BudTypeScript extends Extension { * {@link Extension.register} */ @bind - public override async register(bud: Bud) { + public override async register({build, context, hooks}: Bud) { const loader = await this.resolve(`ts-loader`, import.meta.url) + if (!loader) return this.logger.error(`ts-loader not found`) + const typescript = await this.resolve(`typescript`, import.meta.url) + if (!typescript) return this.logger.error(`typescript not found`) /** * If a tsconfig.json file is present */ - if (bud.context.files[`tsconfig.json`]) { + if (context.files[`tsconfig.json`]) { // Set the tsconfig.json file path - this.set(`configFile`, bud.context.files[`tsconfig.json`].path) + this.set(`configFile`, context.files[`tsconfig.json`].path) } /** * Set the compiler and context options */ - this.set(`compiler`, typescript).set(`context`, bud.context.basedir) + this.set(`compiler`, typescript).set(`context`, context.basedir) /** * Resolve .ts, .tsx, .jsx extensions */ - bud.hooks.on(`build.resolve.extensions`, (extensions = new Set([])) => + hooks.on(`build.resolve.extensions`, (extensions = new Set([])) => extensions .add(`.ts`) .add(`.jsx`) @@ -90,7 +93,12 @@ export default class BudTypeScript extends Extension { .add(`.cts`), ) - bud.build + hooks.on(`build.resolveLoader.alias`, (alias = {}) => ({ + ...alias, + [`ts-loader`]: loader, + })) + + build .setLoader(`ts`, loader) .setItem(`ts`, { loader: `ts`, @@ -108,7 +116,7 @@ export default class BudTypeScript extends Extension { * {@link Extension.configAfter} */ @bind - public override async buildBefore(bud: Bud) { + public override async buildBefore({build}: Bud) { /** * Warn if no tsconfig.json was found or explicitly provided */ @@ -120,13 +128,13 @@ export default class BudTypeScript extends Extension { /** * The `babel` option is not a ts-loader option, so we'll omit it */ - bud.build.items.ts.setOptions(omit(this.options, `babel`)) + build.items.ts.setOptions(omit(this.options, `babel`)) - const items = [bud.build.items.ts] - if (this.get(`babel`) && bud.build.items.babel) - items.unshift(bud.build.items.babel) + const items = [build.items.ts] + if (this.get(`babel`) && `babel` in build.items.babel) + items.unshift(build.items.babel) - bud.build.rules.ts.setUse(items) - bud.build.rules.js.setUse(items) + build.rules.ts.setUse(items) + build.rules.js.setUse(items) } } diff --git a/sources/@roots/bud-vue/src/extension.ts b/sources/@roots/bud-vue/src/extension.ts index dd053537a7..05b192313d 100644 --- a/sources/@roots/bud-vue/src/extension.ts +++ b/sources/@roots/bud-vue/src/extension.ts @@ -54,8 +54,20 @@ export default class Vue extends Extension< * {@link Extension.register} */ @bind - public override async register(bud: Bud) { - bud.build + public override async register({build, hooks}: Bud) { + const loader = await this.resolve(`vue-loader`, import.meta.url) + if (!loader) return this.logger.error(`vue-loader not found`) + + const style = await this.resolve(`vue-style-loader`, import.meta.url) + if (!style) return this.logger.error(`vue-style-loader not found`) + + hooks.on(`build.resolveLoader.alias`, (aliases = {}) => ({ + ...aliases, + [`vue-loader`]: loader, + [`vue-style-loader`]: style, + })) + + build .setLoader(`vue`, await this.resolve(`vue-loader`, import.meta.url)) .setLoader( `vue-style`, @@ -64,7 +76,7 @@ export default class Vue extends Extension< .setItem(`vue`, {ident: `vue`, loader: `vue`}) .setItem(`vue-style`, {ident: `vue-style`, loader: `vue-style`}) - bud.hooks.on(`build.resolve.extensions`, (extensions = new Set()) => + hooks.on(`build.resolve.extensions`, (extensions = new Set()) => extensions.add(`.vue`), ) } diff --git a/sources/@roots/sage/src/blade-loader/extension.ts b/sources/@roots/sage/src/blade-loader/extension.ts index dcc6cc24ae..db36e30449 100644 --- a/sources/@roots/sage/src/blade-loader/extension.ts +++ b/sources/@roots/sage/src/blade-loader/extension.ts @@ -12,8 +12,8 @@ export class BladeLoaderExtension extends Extension { /** * {@link Extension.register} */ - public override async register(bud: Bud) { - bud.hooks.on(`build.resolve.extensions`, (extensions = new Set([])) => + public override async register({hooks}: Bud) { + hooks.on(`build.resolve.extensions`, (extensions = new Set([])) => extensions.add(`.blade.php`), ) }