我使用
pnpm create vite
搭建了一个新的vite项目。为了使其可重复,这些是我在出现提示时的选择:
我想使用 TypeScript 来生成生成的
./server.js
,而不仅仅是 ./src
中的代码,所以我将 server.js
“转换”(即现在重命名)为 server.ts
。
此时我意识到我必须自己构建
./server.ts
,并让 vite 构建所谓的服务器端入口点 ./src/entry-server.ts
。
我使用 vite 来避免必须配置构建 TypeScript 的噩梦,所以我想知道将
./server.ts
本身设置为 SSR 构建的入口点是否可行?这样,SSR 仍然可以工作。
我陷入困境的部分是如何实际导入
./src/entry-server.ts
,现在 ./server.ts
是我的入口点(即 render = (await import('./dist/server/entry-server.js')).render
现在不再构建 entry-server.js
不再工作)。
我有一些工作。这是我所做的,以防对其他人有用:
./vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path';
import { PORT, STATIC_URL } from './src/lib/env';
export default defineConfig(({ command, mode }) => {
const buildTarget = process.env.BUILD_TARGET;
// Common configuration used for both dev and building.
const baseConfig = {
plugins: [vue()],
server: {
host: '127.0.0.1',
port: PORT,
hmr: {
host: '127.0.0.1',
},
},
resolve: {
alias: {
'@': path.resolve(__dirname, 'src')
}
}
};
// Build-specific options
if (buildTarget === 'entry-client') {
return {
...baseConfig,
base: STATIC_URL,
build: {
outDir: 'dist/client'
}
};
} else if (buildTarget === 'entry-server') {
return {
...baseConfig,
base: STATIC_URL,
build: {
manifest: true,
ssr: 'src/entry-server.ts',
outDir: 'dist/server'
}
};
} else if (buildTarget === 'node-server') {
return {
...baseConfig,
publicDir: false,
base: STATIC_URL,
build: {
ssr: 'server.ts',
outDir: 'dist/node',
}
};
} else {
return baseConfig;
}
});
package.json
脚本部分:
"scripts": {
"build:ssr-entry-client": "BUILD_TARGET=entry-client vite build",
"build:ssr-entry-server": "BUILD_TARGET=entry-server vite build",
"build:ssr-node-server": "BUILD_TARGET=node-server vite build",
"build:ssr": "npm run build:ssr-entry-client && npm run build:ssr-entry-server && npm run build:ssr-node-server",
"dev": "nodemon --exec tsx server.ts --watch server.ts --watch src --ext ts,js --ignore dist --ignore node_modules",
"prod": "pnpm build:ssr && NODE_ENV=production node dist/node/server.js"
},
最后,在我的 server.ts 中,我有一个解析实用程序来绝对解析路径:
// Detect absolute path to /frontend
function getRootDir(): string {
const currentPath = process.cwd();
const frontendIndex = currentPath.indexOf('/frontend');
return currentPath.slice(0, frontendIndex + '/frontend'.length);
}
const rootDir = getRootDir();
function resolve(p: string): string {
return path.resolve(rootDir, p);
}
// Wrap server creation to avoid top level await's.
async function createServer() {
// Cached page chrome
const templateHtml = isProduction
? await fs.readFile(resolve('dist/client/index.html'), 'utf-8')
: ''
...
使用我的
resolve
实用程序进行动态文件加载/导入的一个副作用是导入import render = (await import(resolve('dist/server/entry-server.js'))).render
(注意它现在被包裹在resolve
中),这在我的问题中对我来说是有问题的,现在对vite来说是不透明的,因此对于 node-server
构建,vite 不会为 entry-server.js
及其传递依赖项生成资产。在这一点上,这对我来说似乎是一次幸福的意外;我已经把所有的东西都内置了dist/server
。