Skip to content

Commit

Permalink
feat(bundler-farm): mvp
Browse files Browse the repository at this point in the history
  • Loading branch information
typed-sigterm committed Jul 2, 2024
1 parent ca5f969 commit 01c47d9
Show file tree
Hide file tree
Showing 15 changed files with 928 additions and 7 deletions.
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: ['webpack', 'farm', 'vite']

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
5 changes: 5 additions & 0 deletions e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,24 @@
"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": {
"@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:*",
"sass": "^1.77.6",
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" />
65 changes: 65 additions & 0 deletions packages/bundler-farm/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
"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",
"@vuepress/client": "workspace:*",
"@vuepress/core": "workspace:*",
"@vuepress/utils": "workspace:*",
"@vuepress/vite-kit": "workspace:*",
"vue": "^3.4.29"
},
"devDependencies": {
"rollup": "^4.18.0"
},
"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)])
})
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'))
}
}
30 changes: 30 additions & 0 deletions packages/bundler-farm/src/dev.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
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 })
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 ?? {},
})
27 changes: 27 additions & 0 deletions packages/bundler-farm/src/resolveFarmConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { App } from '@vuepress/core'
import { vuepressMainPlugin, vuepressVuePlugin } from '@vuepress/vite-kit'
import { vuepressUserConfigPlugin } from './plugins/index.js'
import type { FarmBundlerOptions, FarmOptions } from './types.js'

export const resolveFarmConfig = async ({
app,
options,
isBuild,
isServer,
}: {
app: App
options: FarmBundlerOptions
isBuild: boolean
isServer: boolean
}): Promise<FarmOptions> => {
return {
clearScreen: false,
...options.farmOptions,
vitePlugins: [
vuepressVuePlugin(options.vuePluginOptions ?? {}),
vuepressMainPlugin({ app, isBuild, isServer }),
vuepressUserConfigPlugin(options),
...(options.farmOptions?.vitePlugins ?? []),
],
}
}
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
}
Loading

0 comments on commit 01c47d9

Please sign in to comment.