-
Notifications
You must be signed in to change notification settings - Fork 920
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/// <reference types="@vuepress/vite-kit/client" /> |
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" | ||
} | ||
} |
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 GitHub Actions / check (macos-latest, 20)
Check failure on line 33 in packages/bundler-farm/src/build.ts GitHub Actions / check (macos-latest, 20)
Check failure on line 33 in packages/bundler-farm/src/build.ts GitHub Actions / check (macos-latest, 18)
Check failure on line 33 in packages/bundler-farm/src/build.ts GitHub Actions / check (macos-latest, 18)
Check failure on line 33 in packages/bundler-farm/src/build.ts GitHub Actions / check (macos-latest, 22)
Check failure on line 33 in packages/bundler-farm/src/build.ts GitHub Actions / check (macos-latest, 22)
Check failure on line 33 in packages/bundler-farm/src/build.ts GitHub Actions / check (ubuntu-latest, 20)
Check failure on line 33 in packages/bundler-farm/src/build.ts GitHub Actions / check (ubuntu-latest, 20)
Check failure on line 33 in packages/bundler-farm/src/build.ts GitHub Actions / check (ubuntu-latest, 22)
Check failure on line 33 in packages/bundler-farm/src/build.ts GitHub Actions / check (ubuntu-latest, 22)
Check failure on line 33 in packages/bundler-farm/src/build.ts GitHub Actions / check (ubuntu-latest, 18)
Check failure on line 33 in packages/bundler-farm/src/build.ts GitHub Actions / check (ubuntu-latest, 18)
Check failure on line 33 in packages/bundler-farm/src/build.ts GitHub Actions / check (windows-latest, 22)
Check failure on line 33 in packages/bundler-farm/src/build.ts GitHub Actions / check (windows-latest, 22)
Check failure on line 33 in packages/bundler-farm/src/build.ts GitHub Actions / check (windows-latest, 20)
Check failure on line 33 in packages/bundler-farm/src/build.ts GitHub Actions / check (windows-latest, 20)
Check failure on line 33 in packages/bundler-farm/src/build.ts GitHub Actions / check (windows-latest, 18)
|
||
}) | ||
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')) | ||
} | ||
} |
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) | ||
} |
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), | ||
}) |
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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './vuepressUserConfigPlugin.js' |
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 ?? {}, | ||
}) |
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, | ||
) | ||
} |
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 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
/// <reference types="vite/client" /> | ||
/// <reference types="@vuepress/vite-kit/client" /> |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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'snode_modules
, which is a problem when using Monorepo. So putcore-js
in the root package to ensurecore-js
can be resolved and not unnecessarily increase the number of dependencies on other packages.