vue3+vite+nodejs,通过接口的形式请求后端打包(可打包全部或指定打包组件)

项目地址https://gitee.com/sybb011016/test_build

打包通过按钮的形式请求接口,让后端进行打包,后端使用express-generator搭建模版。前端项目就在npm init vue@latest基础上添加了路由

如果只想打包AboutView组件,首先修改后端接口。

javascript 复制代码
//打包的测试接口
router.get("/build", function (req, res) {
  //打包的文件路径
  const frontendProjectPath = "E:\\BaiduNetdiskDownload\\Vue.js\\vue_build";
  const component = req.query.component || ""; //传入的参数
  //根据参数决定打包指定目录还是全部打包 cross-env需要前端下载,运行的时候动态设置环境变量
  const buildCommand = component
    ? `cross-env BUILD_COMPONENT=${component} npm run build`
    : `npm run build`;

  exec(buildCommand, { cwd: frontendProjectPath }, (err, stdout, stderr) => {
    if (err) {
      console.error(`exec error: ${err}`);
      return res.status(500).send(`Error during build: ${err.message}`);
    }
    console.log(`stdout: ${stdout}`);
    console.error(`stderr: ${stderr}`);
    res.send("Build completed successfully");
  });
});

前端部分接口如下

javascript 复制代码
export const buildAPI = (comp) => {
  return request({
    url: "/build",
    method: "GET",
    params: {
      component: comp,
    },
  });
};
javascript 复制代码
let res = await buildAPI("About");

修改vite.config.ts配置

javascript 复制代码
export default defineConfig(({ command, mode }) => {
  //后端接口执行的时候会设置环境变量
  const input = process.env.BUILD_COMPONENT
    ? path.resolve(
        __dirname,
        `src/views/${process.env.BUILD_COMPONENT}View.vue`
      )
    : path.resolve(__dirname, "index.html");

  return {
    ....
    build: {
      rollupOptions: {
        input,
      },
    },
  };
});


上面只是打包aboutview相关的js和css,但是并没有html查看,现在为aboutview添加一个html和js作为入口文件用于汇众所有的相关的数据。

修改vite.config.ts文件内容,下面插件的功能主要是为了修改打包后的入口文件名为index。base: "./"该属性必须添加,否则打包后的目录进行本地预览会显示文件的情况,建议也把重命名的方法添加上,否则刷新可能还是会出现本地文件夹的情况

javascript 复制代码
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import path from "node:path";
import { fileURLToPath, URL } from "node:url";
import fs from "fs/promises";

//重命名打包后的about-view.html文件为index.html
const renamePlugin = (originalName, newName) => {
  return {
    name: "rename-output-html",
    closeBundle: async () => {
      const distPath = path.resolve(__dirname, "dist");
      const originalPath = path.join(distPath, originalName);
      const newPath = path.join(distPath, newName);
      try {
        await fs.rename(originalPath, newPath);
        console.log(`Renamed ${originalName} to ${newName}`);
      } catch (err) {
        console.error(`Failed to rename ${originalName} to ${newName}:`, err);
      }
    },
  };
};

export default defineConfig(() => {
  // 检测是否设置了环境变量BUILD_COMPONENT
  const isComponentBuild = process.env.BUILD_COMPONENT;

  return {
    .....
    base: "./",
    plugins: [vue(), renamePlugin("about-view.html", "index.html")],
    build: {
      rollupOptions: {
        input:
          isComponentBuild == "About"
            ? path.resolve(__dirname, "about-view.html")
            : path.resolve(__dirname, "index.html"),
        output: {
          entryFileNames: "assets/[name]-[hash].js", //打包后的index [name]代表使用组件原有名字 [hash]代表hash随机值
          chunkFileNames: "assets/[name]-[hash].js", //打包后各个组件名的js
          assetFileNames: "assets/[name]-[hash].[ext]", //打包后各个组件的css
        },
      },
      outDir: "dist",
    },
  };
});

不使用插件

使用插件

现在我们添加单独的路由模块(这里假设我们的AboutView中需要读取router.params中的某属性),因此在单独打包之前需要在AboutView.js中创建并引入路由模块,注意这里需要配置单独的路由地址。

javascript 复制代码
import { createApp } from "vue";
import AboutView from "./AboutView.vue";

import { createRouter, createWebHistory } from "vue-router";

const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: "/about",
      name: "about",
      component: AboutView,
    },
  ],
});

createApp(AboutView).use(router).mount("#app");

模拟请求传参返回随机数更新标题。这里route.params.id只是随便模拟的东西,无值,主要是验证route非空,未单独引入use(router)的情况下读取未undefined。

javascript 复制代码
const route = useRoute();
const title = ref("This is an about page");
onMounted(() => {
  console.log(route);
  getDataAPI(route.params.id).then((res) => {
    title.value = res.data.title;
  });
});

然后将AboutView的文件单独打包,这里直接部署到宝塔的本地环境中。需要修改一些nginx的参数。文件上传到如下结构。

配置nginx

javascript 复制代码
location / { 
		try_files $uri $uri/ /index.html last;
 		index index.html; 
} 
location /api {
        proxy_pass http://127.0.0.1:3001;
        rewrite ^/api/(.*)$ /$1 break;
}
    //下面选择性添加
 add_header 'Access-Control-Allow-Origin' '*' always; #允许来自所有的访问地址 add_header 'Access-Control-Allow-Credentials' 'true' always; #允许来自所有的访问地址 add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept, token, platform' always; add_header 'Access-Control-Allow-Methods' 'GET,POST,PUT,DELETE,HEAD,OPTIONS' always; #允许来自所有的访问地址

运行单独打包的AboutView

可以正确访问接受数据更新

相关推荐
彭世瑜14 分钟前
ts: TypeScript跳过检查/忽略类型检查
前端·javascript·typescript
FØund40414 分钟前
antd form.setFieldsValue问题总结
前端·react.js·typescript·html
Backstroke fish15 分钟前
Token刷新机制
前端·javascript·vue.js·typescript·vue
小五Five16 分钟前
TypeScript项目中Axios的封装
开发语言·前端·javascript
小曲程序16 分钟前
vue3 封装request请求
java·前端·typescript·vue
临枫54117 分钟前
Nuxt3封装网络请求 useFetch & $fetch
前端·javascript·vue.js·typescript
前端每日三省18 分钟前
面试题-TS(八):什么是装饰器(decorators)?如何在 TypeScript 中使用它们?
开发语言·前端·javascript
小刺猬_98519 分钟前
(超详细)数组方法 ——— splice( )
前端·javascript·typescript
渊兮兮20 分钟前
Vue3 + TypeScript +动画,实现动态登陆页面
前端·javascript·css·typescript·动画
鑫宝Code20 分钟前
【TS】TypeScript中的接口(Interface):对象类型的强大工具
前端·javascript·typescript