likes
comments
collection
share

Vue2从Webpack 迁移到 vite

作者站长头像
站长
· 阅读数 52

vue2项目要从webpack 迁移到 vite 需要完成以下几步

  1. 安装vite 的依赖包
  2. 添加 vite 的配置文件 vite.config.js
  3. 修改文件,包入口 index.html 和 其他文件
  4. 运行 vitevite build 根据报错,修改文件
  5. 删除无用的文件和依赖包

安装vite的依赖包

如果 vue 的版本 >= 2.7.0 使用 @vitejs/plugin-vue2

否则使用 vite-plugin-vue2

yarn add vite vite-plugin-vue2 -D

添加 vite 配置文件

项目根目录下添加 vite.config.js 文件

import { defineConfig } from 'vite'
import { createVuePlugin } from 'vite-plugin-vue2'
import { viteCommonjs } from '@originjs/vite-plugin-commonjs'

export default defineConfig({
    plugins: [
        createVuePlugin({
            jsx: true // 如果有sfc组件需要添加这一行
        }),
        viteCommonjs()
    ]
})

迁移 vue.config.js 配置

迁移 devServer

vite.config.js 中支持配置 serve,和 webpackdevServer 差不多,区别是 rewrite,在 vite 中是一个函数,返回重写后的值.

vite 默认不能通过 ip 访问,需要设置 host: '0.0.0.0'

 server: {
    host: '0.0.0.0',
    proxy: {
        '/test1': {
            target: 'http://localhost:8080',
            changeOrigin: true,
            secure: false,
        },
        '/test2': {
            target: 'http://localhost:8081',
            changeOrigin: true,
            secure: false,
        }
    }
}

迁移 svg-sprite-loader

vite 中使用 vite-plugin-svg-icons 实现和 webpack 中的 svg-sprite-loader 相同的功能

import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import path from 'path'

{
    plugins: [
        createSvgIconsPlugin({
            // 这个目录直接配置成 .svg 文件所在的目录
            iconDirs: [path.resolve("src/icons/svg")],
            symbolId: "icon-[name]",
        })
    ],
}

main.js 中添加 import 'virtual:svg-icons-register'

删除手动引入 svg 目录下的 *.svg 的代码

const req = require.context('./svg', false, /.svg$/)
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)

配置 @ 别名

{
    resolve: {
        alias: {
            "@": path.resolve("src")
        }
    }
}

配置使用jsx 语法

{
    esbuild: {
        loader: {
            ".js": "jsx"
        }
    }
}

修改文件

修改入口文件

vite的入口文件默认是项目根目录下的 index.html,所以需要把 public 目录下的 index.html 移动到项目根目录下

注意事项

  1. Vite 不支持 index.html 中的 ejs 模版,删除 <%= htmlWebpackPlugin.options.title %> 等语法。
  2. Vite 需要在 index.html 引入入口js文件,即添加<script type="module" src="/src/main.js"></script>

修改文件中的 require.context

require.context 替换成 import.meta.globEager,例如

// require.context
const modulesFiles = require.context('./modules', true, /.js$/)
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
  const moduleName = modulePath.replace(/^./(.*).\w+$/, '$1')
  const value = modulesFiles(modulePath)
  modules[moduleName] = value.default
  return modules
}, {})
// import.meta.glob
const modulesFiles = import.meta.globEager("./modules/*.js");
const modules = Object.keys(modulesFiles).reduce((modules, modulePath) => {
  const moduleName = modulePath.replace(/^./modules/(.*).\w+$/, '$1')
  const value = modulesFiles[modulePath]
  modules[moduleName] = value.default
  return modules
}, {})

修改文件中的 process.env

vite 中没有 process.env,所有环境变量都通过 import.meta.env 获取,并且 import.meta.env 不能解构

自定义环境变量只能以 VITE_ 开头,所以这里还需要修改 .env.* 的文件

// process.env
process.env.VUE_APP_BASE_API
// import.meta.env
import.meta.env.VITE_APP_BASE_API

修改 scss 文件名

这一步不是必须的,但是如果你在 js 中使用 scss的变量,那么 scss 文件名必须是以 .module.scss 结尾的

使用 .module.scss 结尾之后,文件会被 postcss-modules 插件处理,最后的类名会被修改掉,稳妥一点的办法是新建一个.module.scss 后缀的文件,导入原来的文件,并导出需要给 js使用的变量

@import "./variables.scss";

:export {
  menuText: $menuText;
  menuActiveText: $menuActiveText;
  subMenuActiveText: $subMenuActiveText;
  menuBg: $menuBg;
  menuHover: $menuHover;
  subMenuBg: $subMenuBg;
  subMenuHover: $subMenuHover;
  sideBarWidth: $sideBarWidth;
}

修改命令

{
    "serve": "vite",
    "build": "vite build"
}

运行 servebuild

运行之后一定会出现一些异常,先根据报错提示修复一波,下面列出了一些常见的错误.

删除不需要的资源

  1. 删除文件 vue.config.js
  2. 删除不需要的依赖包 @vue/cli-service@vue/cli-plugin-eslint

删除包之后,在启动的时候可能会提示缺少依赖包,在根据报错安装上对应的包就可以了

异常处理

  1. EISDIR: illegal operation on a directory, read

    1. 出现这个问题是因为有访问的资源不存在,比如 src="" 或者 href=""

    2. 引入 vue 文件的时候,没有加 .vue 的后缀,或者没有 index.vue 的文件路径

      关于这个问题还有一个解决方案:添加 vite 的扩展名 .vue

{
    resolve: {
        extensions: ['.mjs', '.js', '.mts', '.ts', '.jsx', '.tsx', '.json', '.vue']
    }
}
  1. 使用 @import "~element-ui/packages/theme-chalk/src/index"; 错误

vite 解析不了 scss 文件路径前面的~,所以要删掉

  1. warning: Component /Users/aibee/workspace/ar-manager-platform/src/components/ai-design/ai-input/ai-input.vue uses lang html for template. Please install the language preprocessor.

因为在 .vue 文件的 template 上添加了 lang="html" ,要删掉

  1. Sfc 组件需要在script block中加上lang=jsx的标识
  2. Uncaught SyntaxError: The requested module '/node_modules/.vite/deps/path-to-regexp.js?v=ff233f48' does not provide an export named 'default'

使用的模块没有默认的导出,使用 * as 方式倒入,例如 import * as pathToRegexp from 'path-to-regexp'

  1. Uncaught SyntaxError: The requested module '/node_modules/.vite/deps/core-js_modules_es__function__name__js.js?v=a268d058' does not provide an export named 'default'

browserslist 中添加 not ie 11, browserslistpackage.json 中或者 .browserslist 文件中

  1. Uncaught ReferenceError: Cannot access 'Layout' before initialization

注意这里可能是出现了循环引用,如果是组件引用导致的,可以把组件引用改成懒加载的方式

  1. Error in render: "Error: Module "path" has been externalized for browser compatibility. Cannot access "path.resolve" in client code.

使用 path-browserify 模块 yarn add path-browserify -S

import path from 'path' 都改成 import path from 'path-browserify'

转载自:https://juejin.cn/post/7231448641976811577
评论
请登录