Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add @vuepress/bundler-farm #1583

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node: ['18', '20', '22']
bundler: ['webpack', 'vite']
bundler: ['farm', 'vite', 'webpack']

runs-on: ${{ matrix.os }}

Expand Down
15 changes: 9 additions & 6 deletions e2e/docs/.vuepress/config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import process from 'node:process'
import { farmBundler } from '@vuepress/bundler-farm'
import { viteBundler } from '@vuepress/bundler-vite'
import { webpackBundler } from '@vuepress/bundler-webpack'
import { defineUserConfig } from 'vuepress'
Expand Down Expand Up @@ -62,13 +63,15 @@ export default defineUserConfig({
bundler:
E2E_BUNDLER === 'webpack'
? webpackBundler()
: viteBundler({
viteOptions: {
optimizeDeps: {
include: ['@vuepress-e2e/conditional-exports'],
: E2E_BUNDLER === 'farm'
? farmBundler()
: viteBundler({
viteOptions: {
optimizeDeps: {
include: ['@vuepress-e2e/conditional-exports'],
},
},
},
}),
}),

theme: e2eTheme(),

Expand Down
8 changes: 8 additions & 0 deletions e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,28 @@
"type": "module",
"scripts": {
"docs:build": "vuepress build docs --clean-cache --clean-temp",
"docs:build-farm": "cross-env E2E_BUNDLER=farm pnpm docs:build",
"docs:build-webpack": "cross-env E2E_BUNDLER=webpack pnpm docs:build",
"docs:clean": "rimraf docs/.vuepress/.temp docs/.vuepress/.cache docs/.vuepress/dist",
"docs:dev": "vuepress dev docs --clean-cache --clean-temp",
"docs:dev-farm": "cross-env E2E_BUNDLER=farm pnpm docs:dev",
"docs:dev-webpack": "cross-env E2E_BUNDLER=webpack pnpm docs:dev",
"docs:serve": "anywhere -s -h localhost -p 9080 -d docs/.vuepress/dist",
"e2e:build": "cross-env E2E_COMMAND=build playwright test",
"e2e:build-farm": "cross-env E2E_COMMAND=build E2E_BUNDLER=farm playwright test",
"e2e:build-webpack": "cross-env E2E_COMMAND=build E2E_BUNDLER=webpack playwright test",
"e2e:dev": "cross-env E2E_COMMAND=dev playwright test",
"e2e:dev-farm": "cross-env E2E_COMMAND=dev E2E_BUNDLER=farm playwright test",
"e2e:dev-webpack": "cross-env E2E_COMMAND=dev E2E_BUNDLER=webpack playwright test"
},
"dependencies": {
"@farmfe/plugin-sass": "^1.0.5",
"@vuepress-e2e/conditional-exports": "file:./modules/conditional-exports",
"@vuepress-e2e/style-exports": "file:./modules/style-exports",
"@vuepress/bundler-farm": "workspace:*",
"@vuepress/bundler-vite": "workspace:*",
"@vuepress/bundler-webpack": "workspace:*",
"core-js": "^3.37.1",
"sass": "^1.77.6",
"sass-loader": "^14.2.1",
"vue": "^3.4.29",
Expand All @@ -28,6 +35,7 @@
"devDependencies": {
"@playwright/test": "^1.44.1",
"anywhere": "^1.6.0",
"core-js": "^3.37.1",
"cross-env": "^7.0.3"
}
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"@vitest/coverage-istanbul": "^1.6.0",
"bumpp": "^9.4.1",
"conventional-changelog-cli": "^5.0.0",
"core-js": "^3.37.1",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May not put it in root?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe upstream bug/design 🤔 Farm currently starts resolving core-js from each dependency's node_modules, which is a problem when using Monorepo. So put core-js in the root package to ensure core-js can be resolved and not unnecessarily increase the number of dependencies on other packages.

"eslint": "^8.57.0",
"eslint-config-vuepress": "^4.10.1",
"eslint-config-vuepress-typescript": "^4.10.1",
Expand Down
12 changes: 12 additions & 0 deletions packages/bundler-farm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# @vuepress/bundler-farm

[![npm](https://badgen.net/npm/v/@vuepress/bundler-vite/next)](https://www.npmjs.com/package/@vuepress/bundler-farm)
[![license](https://badgen.net/github/license/vuepress/core)](https://github.com/vuepress/core/blob/main/LICENSE)

## Documentation

https://v2.vuepress.vuejs.org

## License

[MIT](https://github.com/vuepress/core/blob/main/LICENSE)
1 change: 1 addition & 0 deletions packages/bundler-farm/client.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference types="@vuepress/vite-kit/client" />
69 changes: 69 additions & 0 deletions packages/bundler-farm/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
"name": "@vuepress/bundler-farm",
"version": "2.0.0-rc.14",
"description": "Bundler farm package of VuePress",
"keywords": [
"vuepress-bundler",
"vuepress",
"bundler",
"farm"
],
"homepage": "https://github.com/vuepress",
"bugs": {
"url": "https://github.com/vuepress/core/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/vuepress/core.git"
},
"license": "MIT",
"author": "meteorlxy",
"type": "module",
"exports": {
".": "./dist/index.js",
"./client": "./client.d.ts",
"./package.json": "./package.json"
},
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist",
"client.d.ts"
],
"scripts": {
"build": "tsup",
"clean": "rimraf dist"
},
"dependencies": {
"@farmfe/core": "^1.2.4",
"@farmfe/plugin-sass": "^1.0.5",
"@vuepress/client": "workspace:*",
"@vuepress/core": "workspace:*",
"@vuepress/utils": "workspace:*",
"@vuepress/vite-kit": "workspace:*",
"vue": "^3.4.29"
},
"devDependencies": {
"rollup": "^4.18.0"
},
"peerDependencies": {
"core-js": "^3.37.1"
},
"publishConfig": {
"access": "public"
},
"tsup": {
"clean": true,
"dts": "./src/index.ts",
"entry": [
"./src/index.ts"
],
"format": [
"esm"
],
"outDir": "./dist",
"sourcemap": false,
"target": "es2022",
"tsconfig": "../../tsconfig.dts.json"
}
}
91 changes: 91 additions & 0 deletions packages/bundler-farm/src/build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { build as farmBuild } from '@farmfe/core'
import type { App, Bundler } from '@vuepress/core'
import { debug, fs, withSpinner } from '@vuepress/utils'
import { resolveFarmConfig } from './resolveFarmConfig.js'
import type { FarmBundlerOptions } from './types.js'

const log = debug('vuepress:bundler-vite/build')

export const build = async (
options: FarmBundlerOptions,
app: App,
): ReturnType<Bundler['build']> => {
// plugin hook: extendsBundlerOptions
await app.pluginApi.hooks.extendsBundlerOptions.process(options, app)

// vite compile
log('compiling start')
await withSpinner('Compiling with farm')(async () => {
// create vite config
const clientConfig = await resolveFarmConfig({
app,
options,
isBuild: true,
isServer: false,
})
const serverConfig = await resolveFarmConfig({
app,
options,
isBuild: true,
isServer: true,
})

await Promise.all([farmBuild(clientConfig), farmBuild(serverConfig)])

Check failure on line 33 in packages/bundler-farm/src/build.ts

View workflow job for this annotation

GitHub Actions / check (macos-latest, 20)

Argument of type 'ResolvedUserConfig' is not assignable to parameter of type 'FarmCLIOptions & UserConfig'.

Check failure on line 33 in packages/bundler-farm/src/build.ts

View workflow job for this annotation

GitHub Actions / check (macos-latest, 20)

Argument of type 'ResolvedUserConfig' is not assignable to parameter of type 'FarmCLIOptions & UserConfig'.

Check failure on line 33 in packages/bundler-farm/src/build.ts

View workflow job for this annotation

GitHub Actions / check (macos-latest, 18)

Argument of type 'ResolvedUserConfig' is not assignable to parameter of type 'FarmCLIOptions & UserConfig'.

Check failure on line 33 in packages/bundler-farm/src/build.ts

View workflow job for this annotation

GitHub Actions / check (macos-latest, 18)

Argument of type 'ResolvedUserConfig' is not assignable to parameter of type 'FarmCLIOptions & UserConfig'.

Check failure on line 33 in packages/bundler-farm/src/build.ts

View workflow job for this annotation

GitHub Actions / check (macos-latest, 22)

Argument of type 'ResolvedUserConfig' is not assignable to parameter of type 'FarmCLIOptions & UserConfig'.

Check failure on line 33 in packages/bundler-farm/src/build.ts

View workflow job for this annotation

GitHub Actions / check (macos-latest, 22)

Argument of type 'ResolvedUserConfig' is not assignable to parameter of type 'FarmCLIOptions & UserConfig'.

Check failure on line 33 in packages/bundler-farm/src/build.ts

View workflow job for this annotation

GitHub Actions / check (ubuntu-latest, 20)

Argument of type 'ResolvedUserConfig' is not assignable to parameter of type 'FarmCLIOptions & UserConfig'.

Check failure on line 33 in packages/bundler-farm/src/build.ts

View workflow job for this annotation

GitHub Actions / check (ubuntu-latest, 20)

Argument of type 'ResolvedUserConfig' is not assignable to parameter of type 'FarmCLIOptions & UserConfig'.

Check failure on line 33 in packages/bundler-farm/src/build.ts

View workflow job for this annotation

GitHub Actions / check (ubuntu-latest, 22)

Argument of type 'ResolvedUserConfig' is not assignable to parameter of type 'FarmCLIOptions & UserConfig'.

Check failure on line 33 in packages/bundler-farm/src/build.ts

View workflow job for this annotation

GitHub Actions / check (ubuntu-latest, 22)

Argument of type 'ResolvedUserConfig' is not assignable to parameter of type 'FarmCLIOptions & UserConfig'.

Check failure on line 33 in packages/bundler-farm/src/build.ts

View workflow job for this annotation

GitHub Actions / check (ubuntu-latest, 18)

Argument of type 'ResolvedUserConfig' is not assignable to parameter of type 'FarmCLIOptions & UserConfig'.

Check failure on line 33 in packages/bundler-farm/src/build.ts

View workflow job for this annotation

GitHub Actions / check (ubuntu-latest, 18)

Argument of type 'ResolvedUserConfig' is not assignable to parameter of type 'FarmCLIOptions & UserConfig'.

Check failure on line 33 in packages/bundler-farm/src/build.ts

View workflow job for this annotation

GitHub Actions / check (windows-latest, 22)

Argument of type 'ResolvedUserConfig' is not assignable to parameter of type 'FarmCLIOptions & UserConfig'.

Check failure on line 33 in packages/bundler-farm/src/build.ts

View workflow job for this annotation

GitHub Actions / check (windows-latest, 22)

Argument of type 'ResolvedUserConfig' is not assignable to parameter of type 'FarmCLIOptions & UserConfig'.

Check failure on line 33 in packages/bundler-farm/src/build.ts

View workflow job for this annotation

GitHub Actions / check (windows-latest, 20)

Argument of type 'ResolvedUserConfig' is not assignable to parameter of type 'FarmCLIOptions & UserConfig'.

Check failure on line 33 in packages/bundler-farm/src/build.ts

View workflow job for this annotation

GitHub Actions / check (windows-latest, 20)

Argument of type 'ResolvedUserConfig' is not assignable to parameter of type 'FarmCLIOptions & UserConfig'.

Check failure on line 33 in packages/bundler-farm/src/build.ts

View workflow job for this annotation

GitHub Actions / check (windows-latest, 18)

Argument of type 'ResolvedUserConfig' is not assignable to parameter of type 'FarmCLIOptions & UserConfig'.

Check failure on line 33 in packages/bundler-farm/src/build.ts

View workflow job for this annotation

GitHub Actions / check (windows-latest, 18)

Argument of type 'ResolvedUserConfig' is not assignable to parameter of type 'FarmCLIOptions & UserConfig'.
})
log('compiling finish')

/*
// render pages
await withSpinner(`Rendering ${app.pages.length} pages`)(async (spinner) => {
// get client bundle entry chunk and css asset
const clientEntryChunk = clientOutput.output.find(
(item) => item.type === 'chunk' && item.isEntry,
) as OutputChunk
const clientCssAsset = clientOutput.output.find(
(item): item is OutputAsset =>
item.type === 'asset' && item.fileName.endsWith('.css'),
)

// get server bundle entry chunk
const serverEntryChunk = serverOutput.output.find(
(item) => item.type === 'chunk' && item.isEntry,
) as OutputChunk

// load the compiled server bundle
const serverEntryPath = app.dir.temp('.server', serverEntryChunk.fileName)
const { createVueApp } = await importFile<{
createVueApp: CreateVueAppFunction
}>(serverEntryPath)
// create vue ssr app
const { app: vueApp, router: vueRouter } = await createVueApp()
const { renderToString } = await import('vue/server-renderer')

// load ssr template file
const ssrTemplate = await fs.readFile(app.options.templateBuild, {
encoding: 'utf8',
})

// pre-render pages to html files
for (const page of app.pages) {
if (spinner) spinner.text = `Rendering pages ${colors.magenta(page.path)}`
await renderPage({
app,
page,
vueApp,
vueRouter,
renderToString,
ssrTemplate,
output: clientOutput.output,
outputEntryChunk: clientEntryChunk,
outputCssAsset: clientCssAsset,
})
}
})
*/

// keep the server bundle files in debug mode
if (!app.env.isDebug) {
// remove server temp directory after pages rendered
await fs.remove(app.dir.temp('.server'))
}
}
33 changes: 33 additions & 0 deletions packages/bundler-farm/src/dev.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Compiler, DEFAULT_HMR_OPTIONS, logger, Server } from '@farmfe/core'
import type { App, Bundler } from '@vuepress/core'
import { resolveFarmConfig } from './resolveFarmConfig.js'
import type { FarmBundlerOptions } from './types.js'
export const dev = async (
options: FarmBundlerOptions,
app: App,
): ReturnType<Bundler['dev']> => {
// plugin hook: extendsBundlerOptions
await app.pluginApi.hooks.extendsBundlerOptions.process(options, app)

const farmConfig = await resolveFarmConfig({
app,
options,
isBuild: false,
isServer: false,
})

const compiler = new Compiler({
config: farmConfig.compilation,
jsPlugins: [],
rustPlugins: [],
})
const server = new Server({ compiler, logger })
// @ts-expect-error wrong types? todo
await server.createDevServer({
...farmConfig.server,
hmr: DEFAULT_HMR_OPTIONS,
})
await server.listen()

return server.close.bind(server)
}
10 changes: 10 additions & 0 deletions packages/bundler-farm/src/farmBundler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { Bundler } from '@vuepress/core'
import { build } from './build.js'
import { dev } from './dev.js'
import type { FarmBundlerOptions } from './types.js'

export const farmBundler = (options: FarmBundlerOptions = {}): Bundler => ({
name: '@vuepress/bundler-farm',
dev: (app) => dev(options, app),
build: (app) => build(options, app),
})
5 changes: 5 additions & 0 deletions packages/bundler-farm/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { farmBundler } from './farmBundler.js'

export * from './types.js'
export * from './farmBundler.js'
export default farmBundler
1 change: 1 addition & 0 deletions packages/bundler-farm/src/plugins/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './vuepressUserConfigPlugin.js'
12 changes: 12 additions & 0 deletions packages/bundler-farm/src/plugins/vuepressUserConfigPlugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { JsPlugin } from '@farmfe/core'
import type { FarmBundlerOptions } from '../types.js'

/**
* A plugin to allow user config to override vite config
*/
export const vuepressUserConfigPlugin = (
options: FarmBundlerOptions,
): JsPlugin => ({
name: 'vuepress:user-config',
config: () => options.farmOptions ?? {},
})
39 changes: 39 additions & 0 deletions packages/bundler-farm/src/resolveFarmConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { logger, resolveConfig } from '@farmfe/core'
import type { ResolvedUserConfig } from '@farmfe/core'
import type { App } from '@vuepress/core'
import { vuepressMainPlugin, vuepressVuePlugin } from '@vuepress/vite-kit'
import { vuepressUserConfigPlugin } from './plugins/index.js'
import type { FarmBundlerOptions } from './types.js'

export const resolveFarmConfig = async ({
app,
options,
isBuild,
isServer,
}: {
app: App
options: FarmBundlerOptions
isBuild: boolean
isServer: boolean
}): Promise<ResolvedUserConfig> => {
return await resolveConfig(
{
clearScreen: false,
...options.farmOptions,
plugins: ['@farmfe/plugin-sass', ...(options.farmOptions?.plugins ?? [])],
vitePlugins: [
vuepressVuePlugin(options.vuePluginOptions ?? {}),
vuepressMainPlugin({
app,
isBuild,
isServer,
alwaysWriteEntryHtml: true,
}),
vuepressUserConfigPlugin(options),
...(options.farmOptions?.vitePlugins ?? []),
],
},
isBuild ? 'production' : 'development',
logger,
)
}
15 changes: 15 additions & 0 deletions packages/bundler-farm/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { Server, start } from '@farmfe/core'
import type { VuePluginOptions } from '@vuepress/vite-kit'

export type FarmOptions = Exclude<Parameters<typeof start>[0], undefined>
export type FarmDevServerOptions = Parameters<
InstanceType<typeof Server>['createDevServer']
>[0]

/**
* Options for bundler-vite
*/
export interface FarmBundlerOptions {
farmOptions?: FarmOptions
vuePluginOptions?: VuePluginOptions
}
2 changes: 1 addition & 1 deletion packages/bundler-vite/client.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
/// <reference types="vite/client" />
/// <reference types="@vuepress/vite-kit/client" />
Loading
Loading