• vue2+vite+vue-cli5 实现vite开发webpack打包


    20221008补充一条,如果需要兼容IE,需要修改.browserslistrc为

    > 1%
    last 2 versions
    IE 11
    IE 10
    

    去除自带的not dead,

    1. 为何要用vite开发,但是webpack打包

    主要是因为即想要得到vite的高效开发模式(免编译)但是最后又想要兼容到IE9(ps,vite自带插件最多IE11而且打包出两份代码)

    2. 实现流程

    主要通过利用vue-cli5构建vue2项目(vue3不兼容IE),然后用vite-plugin-vue2实现vite开发(不需要使用它打包)

    2.1 vue-cli5

    推荐升级使用vue-cli5,可以避免很多问题,
    例如vue-cli5默认会出现vue.config.js,
    vue-cli4.3 生成的typescript 的vue项目中typescript版本过低导致报错
    vue-cli4.3 很多vue.config.js的配置无效,例如 runtimeCompiler:true

    npm install -g @vue-cli
    

    2.2 创建vue项目

    Use class-style component syntax 这儿先选择n,如果你希望项目依然可以兼容原来的非class写法的话,这个先选n,后面手动在package.json的dependencies加上

        "vue-class-component": "^7.2.3",
        "vue-property-decorator": "^9.1.2",
    

    最后记得选择In dedicated config files 为Y,
    typescript可选可不选

    2.3 兼容vite

    这部分我参考了这篇文章,但是对其中部分操作进行了修正webpack项目中使用vite加速的兼容模式详解

    2.3.1 index.html处理

    vite需要index.html在根目录,那就把index.html拷贝到根目录,这儿需要删除里面原有的htmlWebpackPlugin相关的代码,否则vite会报错,
    另外还需要注入main函数给index.html

    接下来在根目录下添加command文件夹,并在其中新建htm.js和vite.js(node启动用)
    html.js 主要作用是在webpack打包前把index.html拷贝一份到public目录下

    // ./command/html.js
    const path = require('path')
    const fs = require('fs')
    // 把 index.html 拷贝到 public 下
    fs.copyFileSync(path.resolve('./index.html'), path.resolve('./public/index.html'))
    

    为何不保留public下的index.html呢,这就是一个坑,本人已经踩过了,
    当public下存在index.html时,vite启动后无法正常给index.html注入main函数
    因此需要vite.js

    const path = require('path')
    const fs = require('fs')
    // vite启动时,需要删除public 下的index.html
    if(fs.existsSync(path.resolve('./public/index.html'))){
        fs.unlinkSync(path.resolve('./public/index.html'));
    }
    

    然后就是新建vite.config.js
    在里面配置vite-plugin-html实现main函数注入,具体可以参考之前提到的那篇文章

    然后就是设置vite-plugin-vue2等插件到vite.config.js

    2.3.2 启动项目配置

    package.json中script部分

        "vite": "node ./command/vite.js && vite",
        "serve": "node ./command/html.js && npm run transformJs && vue-cli-service serve",
        "build": "node ./command/html.js && npm run transformJs && vue-cli-service build",
        "transformJs": "babel --plugins @babel/plugin-transform-modules-commonjs --presets=@vue/cli-plugin-babel/preset ./config -d ./config_cm"
    

    我这提示需要babel7.0以上,卸了原来的6.x,重装7.0

    npm uninstall babel-cli
    npm uninstall babel-core
    npm install @babel-cli
    npm uninstall @babel-core
    

    然后安装 @babel/plugin-transform-modules-commonjs 和 @vue/cli-plugin-babel 即可
    npm run vite 表示vite启动

    2.3.3 vite和webpack公用一个调试devServer

    本来其实可以不用的,但是有些情况下,需要即时的看下webpack下的IE兼容情况,而不是每次都需要打包部署后查看
    文章中提供了实现,就是上一节中的babel的作用,但是实际测试发现vue-cli5会检测devServer配置字段,
    在根目录下新建config文件夹,然后新建config/index.js
    20230118补漏,根目录下还要再建一个config_cm/index.js
    因为vue.config.js中无法使用export语法导出的js需要把config/index.js 通过babel转换为config_cm/index.js后,在vue.config.js中引入

    export default function (webpackFlag) {
        let config = {
            host: '0.0.0.0',
            port: 12003,
            https: false,
            proxy: {
                "/_api": {
                    //target: "http://172.27.148.96:8871",
                    //target: "http://32.142.240.253:8871",  //写地址
                    target: "http://localhost:8090",
                    ws: true,  // 允许跨域
                    changeOrigin: true,  //允许跨域
                    /*改动一下,由于vite.config和vue.config path重写不同*/
                    //pathRewrite: {
                    //    "^/_api": ""
                    //},
                    timeout: 60000
                }
            }
        }
        if (webpackFlag === true) {
        /*改动一下,由于vite.config和vue.config path重写不同*/
        	config.proxy["/_api"].pathRewrite ={
                "^/_api": ""
            }
            return config;
        }
        else {
            config = Object.assign(config, {
                hotOnly: true,
                disableHostCheck: true
            })
            /*改动一下,由于vite.config和vue.config path重写不同*/
            config.proxy["/_api"].rewrite=(path) => path.replace(/^\/_api/,'');
            return config;
        }
    }
    

    相比原文章直接导出固定的config会导致vue-cli5启动时检测到不合法的字段而失败,我这儿导出了函数,并支持传入flag得到不同的config。
    相应的vue.config.js中devServer要这么写

    const path = require('path')
    function resolve(dir) {
        return path.join(__dirname, dir)
    }
    const { defineConfig } = require('@vue/cli-service')
    const getDevServer = require(resolve('config_cm')).default  //此处vue.config.js中使用了经过babel转换后的config_cm
    module.exports = defineConfig({
      transpileDependencies: true,
      devServer:getDevServer(true)
    })
    

    vite.config.js中这么写

    import getDevServer from './config/index.js'   //vite中就不需要使用babel转换的代码
    ...
    {
    server:getDevServer(),
    }
    ...
    

    3. 主要配置代码(用了ts)

    vue.config.js 其他配置自己加

    const path = require('path')
    function resolve(dir) {
        return path.join(__dirname, dir)
    }
    const { defineConfig } = require('@vue/cli-service')
    const getDevServer = require(resolve('config_cm')).default
    module.exports = defineConfig({
      transpileDependencies: true,
      devServer:getDevServer(true)
    })
    

    vite.config.js 参考webpack项目中使用vite加速的兼容模式详解 并修改所得

    // vite.config.js
    import getDevServer from './config/index.js'
    import { defineConfig, loadEnv } from 'vite'
    import { createHtmlPlugin } from 'vite-plugin-html'
    import path from 'path'
    import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
    import { createVuePlugin } from "vite-plugin-vue2";
    // import requireTransform from 'vite-plugin-require-transform';
    
    export default defineConfig(({ mode }) => {
        const envPrefix = ['VUE']
        const env = loadEnv(mode, process.cwd(), envPrefix)
        const define = {
            'process.env.NODE_ENV': '"development"',
            'process.env.BASE_URL': '"/"',
            'process.env.VITE': true
        }
        for (const [key, value] of Object.entries(env)) {
            define[`process.env.${key}`] = `"${value}"`
        }
        // 加载环境变量,因为 vite 中不会加载以 VUE 开头的,我们得自己指定下
        return {
            build: {
                // 设置vite打包大小控制
                chunkSizeWarningLimit: 10000,
            },
            resolve: {
                extensions: [".vue", ".mjs", ".js", ".ts", ".jsx", ".tsx", ".json"],
                alias:{
                    '@': path.resolve(__dirname, './src/')
                },
                // alias: [
                //     // 针对以 ~@/[包名称]开头的,替换为 node_modules/@[包名称]
                //     { find: /^(~@)(?!\/)(.+)/, replacement: path.join('node_modules/@$2') },
                //     // 针对以 ~@/ 开头,替换为 src/
                //     { find: /^~@\//, replacement: path.join(__dirname, 'src/') },
                //     // 针对以 @/ 开头的,替换为 src/
                //     { find: /^@\//, replacement: path.join(__dirname, './src', '/') }
                // ],
            },
            server:getDevServer(),
            define,
            plugins: [
                // requireTransform({
                //     fileRegex: /.js$|.vue$|.ts$/
                // }),
                createSvgIconsPlugin({
                    // 指定要缓存的文件夹
                    iconDirs: [path.resolve(process.cwd(), 'src/assets/svgs')],
                    // 指定symbolId格式
                    symbolId: '[name]'
                }),
                createVuePlugin(),
                createHtmlPlugin({
                    minify: true,
                    template: './index.html',
                    entry: '/src/main.ts', // 这个会帮我们注入入口 js 文件
                    inject: {
                        data: {
                            // 这是我们 index.html 用到的环境变量
                            ...env
                        }
                    }
                })
            ]
        }
    })
    

    package.json部分
    需要class组件写法的加上
    “vue-class-component”: “^7.2.3”,
    “vue-property-decorator”: “^9.1.2”,
    可以实现class组件写法和原来的非class写法在typescript下兼容
    需要注意的是下面的transformJs在使用vue-cli serve或者build时,需要把/config/index.js转换为/config_cm/index.js供vue.config.js使用

    {
      "scripts": {
        "vite": "node ./command/vite.js && vite",
        "serve": "node ./command/html.js && npm run transformJs && vue-cli-service serve",
        "build": "node ./command/html.js && npm run transformJs && vue-cli-service build",
        "transformJs": "babel --plugins @babel/plugin-transform-modules-commonjs --presets=@vue/cli-plugin-babel/preset ./config -d ./config_cm"
      },
      "dependencies": {
        "@babel/plugin-transform-modules-commonjs": "^7.18.6",
        "core-js": "^3.8.3",
        "vite": "^3.1.3",
        "vite-plugin-html": "^3.2.0",
        "vite-plugin-svg-icons": "^2.0.1",
        "vite-plugin-vue2": "^2.0.2",
        "vue": "^2.6.14",
        "vue-class-component": "^7.2.3",
        "vue-property-decorator": "^9.1.2",
        "vue-router": "^3.5.1"
      },
      "devDependencies": {
        "@vue/cli-plugin-babel": "^5.0.8",
        "@vue/cli-plugin-router": "~5.0.0",
        "@vue/cli-plugin-typescript": "~5.0.0",
        "@vue/cli-service": "~5.0.0",
        "less": "^4.0.0",
        "less-loader": "^8.0.0",
        "typescript": "~4.5.5",
        "vue-template-compiler": "^2.6.14"
      }
    }
    

    顺便把tsconfig.json也提供下吧

    {
      "compilerOptions": {
        "experimentalDecorators": true,
        "noImplicitAny":false,
    	  "skipLibCheck": true,
        "target": "esnext",
        "module": "esnext",
        "strict": true,
        "jsx": "preserve",
        "importHelpers": true,
        "moduleResolution": "node",
        "esModuleInterop": true,
        "allowSyntheticDefaultImports": true,
        "sourceMap": true,
        "baseUrl": ".",
        "types": [
          "webpack-env"
        ],
        "paths": {
          "@/*": [
            "src/*"
          ]
        },
        "lib": [
          "esnext",
          "dom",
          "dom.iterable",
          "scripthost"
        ]
      },
      "include": [
        "src/**/*.ts",
        "src/**/*.tsx",
        "src/**/*.vue",
        "tests/**/*.ts",
        "tests/**/*.tsx"
      ],
      "exclude": [
        "node_modules"
      ]
    }
    
    
  • 相关阅读:
    vue简单源码手写,实现基本的模板解析,v-text,v-html,v-on:click,@click基本语法指令
    Jenkins构建Maven项目
    C++ 纠错题总结2
    ThreadLocal的简单理解
    1. 获取数据-requests.get()
    nodejs中如何使用Redis
    常见排序算法
    蓝桥杯算法基础(38)c++ STL
    枚举类中有2个值,如何根据值1取值2,根据值2取值1
    ARM pwn 入门 (3)
  • 原文地址:https://blog.csdn.net/JokerSoulClub/article/details/127126138