20221008补充一条,如果需要兼容IE,需要修改.browserslistrc为
> 1%
last 2 versions
IE 11
IE 10
去除自带的not dead,
主要是因为即想要得到vite的高效开发模式(免编译)但是最后又想要兼容到IE9(ps,vite自带插件最多IE11而且打包出两份代码)
主要通过利用vue-cli5构建vue2项目(vue3不兼容IE),然后用vite-plugin-vue2实现vite开发(不需要使用它打包)
推荐升级使用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
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可选可不选
这部分我参考了这篇文章,但是对其中部分操作进行了修正webpack项目中使用vite加速的兼容模式详解
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
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启动
本来其实可以不用的,但是有些情况下,需要即时的看下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(),
}
...
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"
]
}