You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3文档模板Webpack打包后无法在Express服务导入的SSR问题

Vue SSR文档模板服务构建问题

我正在开发一个文档模板服务,其中包含大量用Vue编写的合同、协议类文档模板。核心逻辑是:客户端在请求体中传入props,这些props会传递给对应的Vue组件(文档模板),渲染后的文档将作为响应返回给客户端。Vue非常适配这个场景——它上手简单,且能支撑复杂模板所需的灵活逻辑环境。

棘手的点在于,每个文档的script部分逻辑都比较复杂,因此我不能只提取组件的template部分结合上下文渲染,必须将Vue模板的所有部分(script setup + TypeScript、template、css)完整转译,再为组件指定上下文(props)。

转译环节我采用了Webpack(搭配vue-loader、ts-loader),并使用CommonJS配置——因为我的Express应用规模较大,切换到ESM需要大量重构,所以无法使用ESM。但Webpack生成的bundle始终无法正常导入,尝试了以下代码:

export async function loadSSRTemplate(templateName: string) {
  // 注:我用的是CommonJS,但这里是未编译的TypeScript代码
  // @ts-ignore
  const bundle = await import('@/ssr/dist/main.js');
  console.log(bundle.default); // 始终返回undefined
  return bundle[templateName]; // 同样无法获取到组件
}

我找不到从bundle中导入转译后Vue组件的方式,也就无法配合createSSRApp和h()方法进行渲染。

我知道没有明确的报错信息(不想让你纠结所有配置和组件结构细节),但想请教有相关经验的人:这种方案是否可行?我是不是在做无用功?

另外,如果有其他可行技术方案也可以推荐,但出于性能考虑,我更倾向于在构建阶段预先完成转译。


技术栈详情

  • 模板侧:Vue 3 + TypeScript + Composition API(script setup) + Webpack 5.9
  • 服务侧:Node 18(Express) + TypeScript,基于Node:18镜像Docker化部署,使用ts-node-dev运行,采用CommonJS配置

补充配置细节

Webpack配置

const path = require('path');
const nodeExternals = require('webpack-node-externals');
const { VueLoaderPlugin } = require('vue-loader/dist/index');

module.exports = {
  target: 'node',
  mode: 'development',
  entry: './webpack-entry-point.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js',
    libraryTarget: 'commonjs2',
  },
  externals: nodeExternals({
    allowlist: /\.css$/,
  }),
  module: {
    rules: [
      {
        test: /\.ts$/,
        loader: 'ts-loader',
        options: { appendTsSuffixTo: [/\.vue$/] },
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader',
      },
    ],
  },
  resolve: {
    alias: {
      '@templates': path.resolve(__dirname, './templates'),
    },
    extensions: ['.ts', '.js', '.vue', '.json'],
  },
  plugins: [new VueLoaderPlugin()],
  optimization: {
    splitChunks: {
      chunks: 'all',
    },
  },
};

Webpack入口文件

import NajomnaZmluva from '@templates/reality_module/NajomnaZmluva.vue';

export { NajomnaZmluva };

模板服务的render方法实现

async render(id: string, data: any): Promise<string> {
  if (!process.env.SSR_DOCUMENT_TEMPLATE_PATH) {
    console.error('SSR_DOCUMENT_TEMPLATE_PATH is not defined');
    throw new UnknownServerError();
  }

  const documentTemplate = await this.retrieve(id);

  if (!documentTemplate.schema) {
    throw new BadRequestError(
      responsesConstants.errors.badRequestError.schemaNotDefined,
    );
  }

  this.validateSchema(
    documentTemplate.schema as Record<string, schemaType>,
    data,
  );

  // 模板名称后续会动态指定,此处仅为测试硬编码
  const Template = await loadSSRTemplate('NajomnaZmluva');

  // 因卡在bundle加载环节,以下代码暂未验证可行性

  const ssrDocument = createSSRApp({
    template: h(Template, { props: data }),
  });

  return await renderToString(ssrDocument);
}

进展更新

我已经取得了突破,几小时后会发布完整解决方案。

内容的提问来源于stack exchange,提问作者Daniel Klimek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 00:09:51