Vue3多文件入口项目本地调试优化-webpack转vite方案总结

背景

前两天写了关于单文件入口项目的webpack转vite方案,这周继续来写一下多文件入口的项目webpack转vite需要怎么来处理。

准备工作

其实跟上次单文件入口的项目一样,都需要一样的配置。

  1. Vite 需要 Node.js 版本 14.18+,16+。
  2. 必要插件:@vitejs/plugin-vue、@vitejs/plugin-vue-jsx(vue2 的项目对应使用的是 vite-plugin-vue2)
  3. 对于 vue3 的项目,因为 @vitejs/plugin-vue 要求 vue 在 3.2.25 版本以上,所以如果是 3.2.25 之前的 vue3 项目,需要先升级,否则项目启动会产生如下报错
js 复制代码
Error: Failed to resolve vue/compiler-sfc.

@vitejs/plugin-vue requires vue (>=3.2.25) to be present in the dependency tree.

步骤

这里我用到了转换插件webpack-to-vite,该工具会根据项目已有配置尽可能匹配的生成新的 vite 配置(无法转换的配置将被忽略),并且将原项目其他改动一并调整后完整复刻到新文件夹下。

js 复制代码
//插件使用命令
npx @originjs/webpack-to-vite <project path>

多入口项目使用 vite-plugin-html 插件结合 build.rollupOptions.input 配置。

以下是执行转换命令后项目的改动点:

  1. 执行命令后会自动创建 src/index.html文件,如果项目部分入口需要一些特殊的包,可在body中补充额外的脚本。
js 复制代码
<!DOCTYPE html>
<html lang="zh">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0" />
    <link rel="icon" href="<%- BASE_URL %>favicon.ico" />
    <title><%- title %></title>
  </head>
  <body>
    <noscript>
      <strong
        >We're sorry but <%- title %> doesn't work properly without
        JavaScript enabled. Please enable it to continue.</strong
      >
    </noscript>
    <div id="app"></div>
    <%- injectScript %>
  </body>
</html>
  1. 执行命令后会自动创建 vite.config.js文件,需要手动新增多入口配置(因为此配置无法自动转换)
js 复制代码
import { defineConfig } from 'vite';
import path from 'path';
import fs from 'fs';
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
import envCompatible from 'vite-plugin-env-compatible';
import { createHtmlPlugin } from 'vite-plugin-html';
import { viteCommonjs } from '@originjs/vite-plugin-commonjs';

const d3List = ['customerMap', 'index', 'stockRightMap'];
const dir = 'vitePublic';
const pages = [];
const input = {};

const updatePagesAndInput = (file) => {
  pages.push({
    entry: `../src/pages/${file}/main.ts`,
    filename: `${file}.html`,
    template: `${dir}/${file}.html`,
    injectOptions: {
      data: {
        title: file,
        BASE_URL: '/',
        injectScript: d3List.includes(file) ? '<script src="/d3.v4.min.js"></script>' : ''
      }
    }
  });
  Object.assign(input, { [file]: path.resolve(__dirname, `${dir}/${file}.html`) });
};

fs.readdirSync('src/pages').forEach((file) => {
  if (!fs.existsSync(`${dir}/${file}.html`)) {
    fs.copyFile('index.html', `${dir}/${file}.html`, (err) => {
      // console.log('----copy err----', err);
      if (!err) {
        updatePagesAndInput(file);
      }
    });
  } else {
    updatePagesAndInput(file);
  }
});

// https://vitejs.dev/config**/**
export default defineConfig({
  resolve: {
    alias: [
      {
        find: '~@',
        replacement: path.resolve(__dirname, 'src')
      },
      {
        find: '@',
        replacement: path.resolve(__dirname, 'src')
      }
    ],
    extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
  },
  plugins: [
    vue(),
    vueJsx(),
    viteCommonjs(),
    envCompatible(),
    createHtmlPlugin({
      minify: true,
      pages
    })
  ],
  base: './',
  css: {
    preprocessorOptions: {
      css: {
        modules: {
          localIdentName: '[local]_[hash:base64:5]'
        },
        localsConvention: 'camelCaseOnly'
      }
    }
  },
  server: {
    strictPort: false,
    port: 8090,
    host: '0.0.0.0',
    https: false,
    proxy: {
      '/test': {
        target: 'XXXXX',
        ws: true,
        changeOrigin: true,
        rewrite: (path) => path.replace(/^/test/, '')
      }
    }
  },
  build: {
    sourcemap: true,
    rollupOptions: {
      input
    }
  }
});
  1. 执行命令后会自动修改package.json,改文件中新增script运行脚本和相应的依赖引入
js 复制代码
{  
  ...
  
  "scripts": {    
    ...
    "serve-vite": "vite",
    "build-vite": "vite build",
    "preview-vite": "vite preview"
  }, 
  
  "devDependencies": {    
    ...    
    "@originjs/vite-plugin-commonjs": "^1.0.1",    
    "@vitejs/plugin-vue": "^2.0.1",
    "@vitejs/plugin-vue-jsx": "^1.3.2",
    "vite": "^2.7.2",
    "vite-plugin-env-compatible": "^1.1.1",
    "vite-plugin-html": "3.2.0",  
  }
  
 }
  1. gitignore 忽略文件
js 复制代码
conversion.log

# vite development entry copy
/vitePublic

项目启动时间对比

原webpack启动时间

现vite启动时间

问题总结

  • 原项目需要先安装准备工作中的项目依赖,否则很多配置项都会转换失败,但不影响项目的转换,在转换过程中可能会报以下错误:
  • 由于该库使用了 vite-plugin-html 插件,启动默认运行 public/index.html,而生成的新项目中只有拷贝到根目录的 index.html 里移除了 webpack 相关的 ejs 语法的代码,而 public/index.html 代码未改动,如果生产打包仍使用 vue-cli,是单入口项目,此处建议注释该插件,手动修改根目录下拷贝的 index.html(移除 ejs 相关代码)。

  • 本文实践多入口项目为非标准的多入口项目,vite-plugin-html 插件会将其判定为单入口,需要拷贝生成各个入口的html文件。

  • Vue版本升级后,运行原来的vue-cli命令部分(5个.vue)文件的ts报错(vite命令不报错),报错原因是:组件声明了属性为'{}',页面中使用组件时没有传任何属性,导致类型不匹配,需删除代码 'props: {},'。

  • 访问地址要加上入口文件夹,例如:http://localhost:8080/vitePublic/XXX.html

相关推荐
Amd7949 小时前
Nuxt.js 应用中的 schema:beforeWrite 事件钩子详解
json·vite·配置·nuxt·验证·钩子·动态
Amd7942 天前
Nuxt.js 应用中的 schema:resolved 事件钩子详解
json·自定义·vite·配置·nuxt·schema·钩子
Amd7942 天前
Nuxt.js 应用中的 vite:extendConfig 事件钩子详解
自定义·开发·vite·配置·nuxt·构建·钩子
Amd7943 天前
Nuxt.js 应用中的 vite:extend 事件钩子详解
自定义·开发·vite·nuxt·插件·构建·钩子
friend_ship5 天前
Vite与Vue Cli的区别与详解
vue.js·webpack·rollup·vite·vue脚手架·vue cli
Amodoro6 天前
解决vite项目tailwindcss不生效!!(Vue3、tailwindcss失效)
前端·javascript·vue.js·vite·tailwindcss
zykk6 天前
一文带你彻底了解vite
前端·面试·vite
王小金Ryan9 天前
开发一个Vite插件,给所有DOM节点插入自定义属性
vue.js·vite
前端霸王防脱发洗发水12 天前
Vite常用插件配置
javascript·vue.js·vite
friend_ship14 天前
Vue3.0都有哪些新特性及优化点
vue.js·vite·vue3.0·es6新特性·proxy响应式对象