Skip to content

Commit

Permalink
🩹 fix(minor): fix ts/vue error (#2623)
Browse files Browse the repository at this point in the history
- Fix: HMR error in projects using `@roots/bud-vue` and `@roots/bud-typescript`. 
- Test: Add e2e tests for `examples/vue-3` and `examples/vue-typescript`


## Type of change

**PATCH: backwards compatible change**
  • Loading branch information
kellymears authored Jul 23, 2024
1 parent b91cc42 commit c57a3ba
Show file tree
Hide file tree
Showing 15 changed files with 655 additions and 105 deletions.
1 change: 1 addition & 0 deletions examples/css-module/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"type": "module",
"devDependencies": {
"@roots/bud": "workspace:*",
"@roots/bud-postcss": "workspace:*",
"@roots/bud-tailwindcss": "workspace:*"
}
}
4 changes: 4 additions & 0 deletions examples/vue-typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
"browserslist": [
"extends @roots/browserslist-config"
],
"dependencies": {
"typescript": "5.5.3",
"vue": "3.4.33"
},
"devDependencies": {
"@roots/bud": "workspace:*",
"@roots/bud-sass": "workspace:*",
Expand Down
2 changes: 1 addition & 1 deletion examples/vue-typescript/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ import {createApp} from 'vue'
import App from './App.vue'

const app = createApp(App)
app.mount('#app')
app.mount('#root')
88 changes: 29 additions & 59 deletions sources/@roots/bud-build/src/config/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ export const module: Factory<`module`> = async ({
path,
}) =>
filter(`build.module`, {
noParse: getNoParse(filter),
noParse: filter(`build.module.noParse`, undefined),
rules: getRules({filter, path, rules}),
unsafeCache: getUnsafeCache(filter),
unsafeCache: filter(`build.module.unsafeCache`, undefined),
})

/**
Expand All @@ -33,7 +33,7 @@ const getRules = ({filter, path, rules}: Props): Array<RuleSetRule> => {
? {
oneOf: [
rules[`inline-image`]?.toWebpack?.(),
rules.image.toWebpack?.(),
rules.image?.toWebpack?.(),
].filter(Boolean),
test: filter(`pattern.image`),
}
Expand All @@ -43,7 +43,7 @@ const getRules = ({filter, path, rules}: Props): Array<RuleSetRule> => {
? {
oneOf: [
rules[`inline-font`]?.toWebpack?.(),
rules.font.toWebpack(),
rules.font?.toWebpack?.(),
].filter(Boolean),
test: filter(`pattern.font`),
}
Expand All @@ -53,65 +53,45 @@ const getRules = ({filter, path, rules}: Props): Array<RuleSetRule> => {
? {
oneOf: [
rules[`inline-svg`]?.toWebpack?.(),
rules.svg.toWebpack(),
rules.svg?.toWebpack?.(),
].filter(Boolean),
test: filter(`pattern.svg`),
}
: undefined,
]),
{
oneOf: [
...filter(`build.module.rules.oneOf`, [
...getDefinedRules({rules}),
...makeIssuerRuleSet({filter, path, rules}),
]),
].filter(Boolean),
},

...filter(`build.module.rules.oneOf`, [
...makeDefinedRuleSet({rules}),
...makeIssuerRuleSet({filter, path, rules}),
]).filter(Boolean),

...filter(`build.module.rules.after`, []),
].filter(Boolean)
}

/**
* Get the standard rules defined in the bud config, extensions, etc.
* Make defined rule set
*/
const getDefinedRules = ({rules}: Partial<Props>) => {
return [
...Object.entries(rules)
.filter(([key, _]) => {
return !DEFINED.includes(key) && !RESOURCES.includes(key)
})
.map(([_, value]) => value),
...DEFINED.map(key => rules[key]),
]
const makeDefinedRuleSet = ({rules}: {rules: Props['rules']}) => {
return Object.entries(rules)
.filter(
([key]) =>
![
`font`,
`image`,
`inline-font`,
`inline-image`,
`inline-svg`,
`svg`,
].includes(key),
)
.map(([, rule]) => rule)
.filter(Boolean)
.map(rule => (`toWebpack` in rule ? rule.toWebpack() : rule))
.map(rule => {
return `toWebpack` in rule ? rule.toWebpack() : rule
})
}

const RESOURCES = [
`image`,
`font`,
`svg`,
`inline-font`,
`inline-image`,
`inline-svg`,
]

const DEFINED = [
`csv`,
`toml`,
`yml`,
`json`,
`html`,
`webp`,
`css-module`,
`css`,
`sass-module`,
`sass`,
`vue`,
`js`,
`ts`,
]

/**
* Get rules for css and css-module imports issued by non-css files.
*/
Expand Down Expand Up @@ -152,13 +132,3 @@ const makeIssuerRuleSet = ({filter, path, rules}: Props) => {

return results
}

const getNoParse = (filter: Props[`filter`]) =>
filter(`build.module.noParse`, undefined)

/**
* By leaving undefined, webpack will strongly cache parsed modules from node_modules
* but leave the rest. This is the default behavior.
*/
const getUnsafeCache = (filter: Props[`filter`]) =>
filter(`build.module.unsafeCache`, undefined)
2 changes: 1 addition & 1 deletion sources/@roots/bud-build/src/items/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ export const css: Factory<Item> = async ({makeItem}) =>
makeItem({
ident: `css`,
loader: `css`,
options: {modules: false},
}).setOptions(({hooks: {filter}}) => ({
modules: false,
sourceMap: isBoolean(filter(`build.devtool`))
? filter(`build.devtool`)
: true,
Expand Down
2 changes: 1 addition & 1 deletion sources/@roots/bud-build/src/rules/css.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type {Factory} from '@roots/bud-build/registry'
const cssModule: Factory = async ({filter, makeRule, path}) =>
makeRule()
.setTest(filter(`pattern.cssModule`))
.setInclude([() => path(`@src`)])
.setInclude([({path}) => path(`@src`)])
.setUse([`precss`, `css-module`])

export {cssModule as default}
6 changes: 3 additions & 3 deletions sources/@roots/bud-framework/src/bootstrap/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export const bootstrap = async (bud: Bud) => {
'location.@modules': bud.context.paths.modules,
'location.@src': bud.context.paths.input,
'location.@storage': bud.context.paths.storage,
'pattern.css': /(?!.*\.module)\.css$/,
'pattern.css': /^(?!.*\.module\.css$).*\.css$/,
'pattern.cssModule': /\.module\.css$/,
'pattern.csv': /\.(csv|tsv)$/,
'pattern.font': /\.(ttf|otf|eot|woff2?|ico)$/,
Expand All @@ -100,8 +100,8 @@ export const bootstrap = async (bud: Bud) => {
'pattern.json5': /\.json5$/,
'pattern.md': /\.md$/,
'pattern.modules': /(node_modules|bower_components|vendor)/,
'pattern.sass': /(?!.*\.module)\.(scss|sass)$/,
'pattern.sassModule': /\.module\.(scss|sass)$/,
'pattern.sass': /^(?!.*\.module\.s[ac]ss$).*\.s[ac]ss$/,
'pattern.sassModule': /\.module\.s[ac]ss$/,
'pattern.svg': /\.svg$/,
'pattern.toml': /\.toml$/,
'pattern.ts': /\.(m?tsx?)$/,
Expand Down
14 changes: 7 additions & 7 deletions sources/@roots/bud-postcss/src/extension/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,16 +120,16 @@ class BudPostCss extends BudPostCssOptionsApi {
}),
})

build.rules.css.setUse((items = []) => [...items, `postcss`])
build.rules[`css-module`]?.setUse((items = []) => [
...items,
`postcss`,
])
build.rules.css.setUse((items = []) =>
items.includes(`postcss`) ? items : [...items, `postcss`],
)
build.rules[`css-module`]?.setUse((items = []) =>
items.includes(`postcss`) ? items : [...items, `postcss`],
)

const config = Object.values(context.files).find(
file => file?.name?.includes(`postcss`) && file?.module,
)

if (config) {
this.logger.log(
`PostCSS configuration is being overridden by project configuration file.`,
Expand Down Expand Up @@ -192,7 +192,7 @@ class BudPostCss extends BudPostCssOptionsApi {
...omit(this.options, [`plugins`, `order`, `postcssOptions`]),
plugins: this.get(`order`).map(this.getPlugin).filter(Boolean),
})
.filter(([k, v]) => !isUndefined(v))
.filter(([, v]) => !isUndefined(v))
.reduce((a, [k, v]) => ({...a, [k]: v}), {})

this.logger.info(`postcss options`, options)
Expand Down
4 changes: 1 addition & 3 deletions sources/@roots/bud-support/src/json5/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
import * as json5 from 'json5'

export default json5
export {default} from 'json5'
59 changes: 29 additions & 30 deletions sources/@roots/bud-vue/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {join} from 'node:path'
import {Extension} from '@roots/bud-framework/extension'
import {
bind,
dependsOnOptional,
expose,
label,
options,
Expand All @@ -32,7 +31,6 @@ interface Options {
version: `^3`,
})
@expose(`vue`)
@dependsOnOptional([`@roots/bud-postcss`, `@roots/bud-sass`])
export default class BudVue extends Extension<
Options,
WebpackPluginInstance
Expand Down Expand Up @@ -192,41 +190,42 @@ export default class BudVue extends Extension<
const style = await this.resolve(`vue-style-loader`, import.meta.url)
if (!style) return this.logger.error(`vue-style-loader not found`)

bud.hooks.on(`build.resolveLoader.alias`, (aliases = {}) => ({
...aliases,
[`vue-loader`]: loader,
[`vue-style-loader`]: style,
}))
bud.hooks
.on(`build.resolveLoader.alias`, (aliases = {}) => ({
...aliases,
[`vue-loader`]: loader,
[`vue-style-loader`]: style,
}))
.hooks.on(`build.resolve.extensions`, (extensions = new Set()) =>
extensions.add(`.vue`),
)

bud.build
.setLoader(`vue`, loader)
.setLoader(`vue-style`, style)
.setItem(`vue`, {ident: `vue`, loader: `vue`})
.setItem(`vue-style`, {ident: `vue-style`, loader: `vue-style`})

await bud.hooks
.on(`build.resolve.extensions`, (extensions = new Set()) =>
extensions.add(`.vue`),
)
.hooks.on(`build.module.rules.before`, (rules = []) => [
...rules,
{
include: [bud.path(`@src`)],
test: bud.hooks.filter(`pattern.vue`),
use: [bud.build.items.vue.toWebpack()],
},
])
.extensions.add({
label: `vue-loader`,
make: async () => {
const {VueLoaderPlugin} = await this.import(
`vue-loader`,
import.meta.url,
{raw: true},
)
return new VueLoaderPlugin()
},
})
bud.hooks.on(`build.module.rules.before`, (rules = []) => [
...rules,
{
include: [bud.path(`@src`)],
test: bud.hooks.filter(`pattern.vue`),
use: [bud.build.items.vue.toWebpack()],
},
])

await bud.extensions.add({
label: `vue-loader`,
make: async () => {
const {VueLoaderPlugin} = await this.import(
`vue-loader`,
import.meta.url,
{raw: true},
)
return new VueLoaderPlugin()
},
})
}

/**
Expand Down
Loading

0 comments on commit c57a3ba

Please sign in to comment.