侧边栏壁纸
博主头像
silianpan博主等级

Feel no regret for this life.

  • 累计撰写 39 篇文章
  • 累计创建 19 个标签
  • 累计收到 0 条评论

全网最硬核的Element-UI从Vue-cli迁移至Vite(二)

silianpan
2022-05-20 / 0 评论 / 0 点赞 / 71 阅读 / 6,793 字
温馨提示:
本文最后更新于 2022-05-20,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

我正在参加「初夏创意投稿大赛」详情请看:初夏创意投稿大赛

一、前言

前不久,对ant-design-vue-pro项目进行了迁移,参考文章:全网最硬核的Ant-Design-Vue从Vue-cli迁移至Vite(一),迁移后的项目地址:GitHub - Seals-Studio/ant-design-vue-pro-vite

本期针对Element-UI库进行迁移,以vue-element-admin项目为例进行迁移,element-ui版本为2.13.2。同时,提供了迁移后的仓库,欢迎Star~

GitHub - Seals-Studio/vue-element-admin-vite

二、背景

众所周知,Vite作为下一代前端开发与构建工具,就是一个字:快。并且Vite已经作为Vue3默认的构建工具。通过实验表明,项目迁移后,从Vue-cli的近2分钟,到Vite的5秒(项目大小不同,时间也不同),提升了几十倍甚至上百倍的速度。

迁移前后对比(参考)

构建工具服务器启动耗时页面首次加载速度 (无缓存)第二次加载速度 (有缓存)热更新 HMR打包
Webpack83s4.78s3.35s4.78s3mins 37s
Vite4.72s (第二次 0.72s)1.71s1.33s瞬间51.45s

三、删除package.json相关依赖

  1. 删除@vue和babel相关

    {
        "@vue/cli-plugin-babel": "4.4.4",
        "@vue/cli-plugin-eslint": "4.4.4",
        "@vue/cli-plugin-unit-jest": "4.4.4",
        "@vue/cli-service": "4.4.4",
        "@vue/test-utils": "1.0.0-beta.29",
        "babel-eslint": "10.1.0",
        "babel-jest": "23.6.0",
        "babel-plugin-dynamic-import-node": "2.3.3",
    }
    
  2. 删除loader(webpack插件)和webpack

    {
        "html-webpack-plugin": "3.2.0",
      	"script-ext-html-webpack-plugin": "2.1.3",
        "sass-loader": "8.0.2",
        "svg-sprite-loader": "4.1.3",
    }
    
  3. 删除babel.conf.jsjsconfig.json

  4. 安装pnpm工具

pnpm是快速的,节省磁盘空间的包管理工具

npm i -g pnpm
# 淘宝源
pnpm config set registry https://registry.npm.taobao.org  
pnpm config set disturl https://npm.taobao.org/dist
pnpm config set NVM_NODEJS_ORG_MIRROR http://npm.taobao.org/mirrors/node  
pnpm config set NVM_IOJS_ORG_MIRROR http://npm.taobao.org/mirrors/iojs  
pnpm config set PHANTOMJS_CDNURL https://npm.taobao.org/dist/phantomjs  
pnpm config set ELECTRON_MIRROR http://npm.taobao.org/mirrors/electron/  
pnpm config set SASS_BINARY_SITE http://npm.taobao.org/mirrors/node-sass  
pnpm config set SQLITE3_BINARY_SITE http://npm.taobao.org/mirrors/sqlite3  
pnpm config set PYTHON_MIRROR http://npm.taobao.org/mirrors/python

四、安装最新版vitevite-plugin-vue2

pnpm add vite vite-plugin-vue2 -D

五、在根目录下新建vite.conf.js

import { defineConfig } from 'vite'
// vue2的vite插件
import { createVuePlugin } from 'vite-plugin-vue2'

export default ({ mode }) => {
  return defineConfig({
    plugins: [
      createVuePlugin({
        jsx: true
      })
    ]
  })
})

六、index.html修改

  • 移动public/index.html到代码根目录(和package.json同级)

  • 在body标签中新增如下:

    <!-- 指明加载main.js -->
    <script type="module" src="/src/main.js"></script>
    
  • 替换htmlWebpackPlugin插件注入的变量

    htmlWebpackPlugin是webpack插件,所以不能再使用了,vite提供了vite-plugin-html插件来向index.html注入变量

    1. 安装vite-plugin-html

      pnpm add vite-plugin-html -D
      
    2. 修改vite.config.js,添加配置

       plugins: [
          // ...
          createHtmlPlugin({
            minify: true,
            inject: {
              data: {
                title: 'vue Element Admin',
                cdn: {
                  css: [],
                  js: [
                        '//cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js',
                        '//cdn.jsdelivr.net/npm/vue-router@3.5.1/dist/vue-router.min.js',
                        '//cdn.jsdelivr.net/npm/vuex@3.1.1/dist/vuex.min.js',
                        '//cdn.jsdelivr.net/npm/axios@0.21.1/dist/axios.min.js'
                  ]
                }
              }
            }
          }),
          // ...
        ]
    
    1. 修改index.html

      • 修改title

        <title><%= title %></title>
        
      • 修改css和js引入

            <!-- require cdn assets css -->
            <% for (var i in cdn.css) { %>
            <link rel="stylesheet" href="<%= cdn.css[i] %>" />
            <% } %>
        
            <!-- require cdn assets js -->
            <% for (var i in cdn.js) { %>
            <script type="text/javascript" src="<%= cdn.js[i] %>"></script>
            <% } %>
        

七、环境变量更换

出于安全考虑,vite只能识别以VITE_开头的环境变量了,原VUE_环境变量不生效了,同时,也不能使用process.env.xxx来读取环境变量了。需要修改vite.conf.js配置,手动添加process.env.xxx环境变量

  • 修改vite.conf.js配置,添加环境变量

    import { defineConfig, loadEnv } from 'vite'
    
    export default ({ mode }) => {  
      const env = loadEnv(mode, process.cwd())
      return defineConfig({
        define: {
          'process.env': { ...env }
        },
      })
    })
    
  • 将所有开头的VUE_环境变量全部替换为VITE_

  • 将所有的process.env.NODE_ENV更改为import.meta.env.MODE

  • 将所有开头为process.env.全部更改为import.meta.env.

八、Element-UI按需引入

  1. 安装vite-plugin-style-import插件
# 注意本插件必须采用1.4.1版本,不能采用最新版2.0.0
pnpm add vite-plugin-style-import@^1.4.1 -D
  1. 增加vite.conf.js配置

    plugins: [
        // ...
        styleImport({
            libs: [
              {
                libraryName: 'element-ui',
                // styleLibraryName: 'theme-chalk',
                esModule: true,
                resolveStyle: (name) => {
                  return `theme-chalk/${name}.css`
                }
              }
            ],
          }),
        // ...
    ]
    

九、添加代理

  1. 安装path-browserify

    pnpm add path-browserify -D
    
  2. 添加vite.conf.js配置

        plugin: [],
        // ...
        server: {
          port: 8000,
          //proxy: {
          //  '/api': {
          //    target: 'https://mock.ihx.me/mock/5baf3052f7da7e07e04a5116/antd-pro',
          //    changeOrigin: true,
          //    ws: false,
          //    rewrite: (path) => path.replace(/^\/api/, ''),
          //  }
          //},
        },
    

十、package.json脚本命令修改

将脚本命令修改为如下:

  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },

十一、postcss配置

  1. 安装插件

    pnpm add postcss autoprefixer -D
    

十二、添加eslint插件

  1. 安装插件

    pnpm remove eslint eslint-plugin-html eslint-plugin-vue
    pnpm add eslint eslint-plugin-html eslint-plugin-vue eslint-config-prettier eslint-plugin-prettier prettier -D
    # vite-eslint插件
    pnpm add vite-plugin-eslint -D
    
  2. 添加vite.conf.js配置

    import eslintPlugin from 'vite-plugin-eslint'
    
    export default ({ mode }) => {
        return defineConfig({
        plugins: [
            // ...
            eslintPlugin(),
            // ...
        ]
       })
    }
    

十三、在写有jsx语法的文件中添加lang="jsx"

<script lang="jsx">
    ...
</script>

十四、添加@别名

修改vite.conf.js配置

export default ({ mode }) => {
    return defineConfig({
       resolve: {
       // ...
         alias: [
           {
              find: /@\/.+/,
              replacement: (val) => {
                  return val.replace(/^@/, path.resolve(__dirname, './src/'))
              },
           },
           {
             // this is required for the SCSS modules
             find: /^~(.*)$/,
             replacement: '$1'
           }
         ]
       },
    )
}

十五、静态文件引入

  1. 动态组件引入

    const modules = import.meta.glob('../views/**/*.vue')
    
    const currentRouter {
        ...
        // component: constantRouterComponents[item.component || item.key] || (() => import(`/src/views/${item.component}`)),
        component: constantRouterComponents[item.component || item.key] || modules[`../views/${item.component}.vue`],
        ...
    }
    
    
    
  2. 静态图片引入

    • 直接import图片

      <template>
          <img :src="LogoImg" />
      </template>
      
      <script>
          import LogoImg from '/src/assets/img/logo.svg'
          export default {
              data() {
                  return {
                      LogoImg
                  }
              }
          }
      </script>
      
    • 采用import.meta.globEager

        1. 图片加载
      ```html
      <template>
          <img :src="getImg('../../assets/img/log.svg')" />
      </template>
      
      <script>
          export default {
              methods: {
                  getImg(path) {
                      const modules = import.meta.globEager('../../assets/img/*.svg')
                      return modules[path].default
                  }
              }
          }
      </script>
      
        1. require.context替换
      // 修改前
      // const req = require.context('./svg', false, /\.svg$/)
      // const requireAll = requireContext => requireContext.keys().map(requireContext)
      
      // 修改后
      const req = import.meta.globEager('./svg/*.svg')
      const requireAll = (requireContext) => Object.keys(requireContext).map((key) => requireContext[key].default)
      
      

十六、雪碧图加载svg-sprite-loader替换

  • 安装vite-plugin-svg-icons插件

    pnpm add vite-plugin-svg-icons -D
    
  • 配置vite.config.js

    import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
    
    defineConfig({
    	plugins: [
    		// ...
    		// 雪碧图
        createSvgIconsPlugin({
            // 指定需要缓存的图标文件夹
            iconDirs: [path.resolve(__dirname, './src/icons/svg')],
            // 指定symbolId格式
            symbolId: 'icon-[dir]-[name]',
    
            /**
             * 自定义插入位置
             * @default: body-last
             */
            inject: 'body-last' | 'body-first',
    
            /**
             * custom dom id
             * @default: __svg__icons__dom__
             */
            customDomId: '__svg__icons__dom__'
          })
    	]
    })
    
  • 在main.js中添加

    import 'virtual:svg-icons-register'
    

迁移后项目地址:GitHub - Seals-Studio/vue-element-admin-vite,欢迎Star~

0

评论区