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目录下
const path = require('path')
const fs = require('fs')
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')
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
export default function (webpackFlag) {
let config = {
host: '0.0.0.0',
port: 12003,
https: false,
proxy: {
"/_api": {
target: "http://localhost:8090",
ws: true,
changeOrigin: true,
pathRewrite: {
"^/_api": ""
},
timeout: 60000
}
}
}
if (webpackFlag === true) {
return config;
}
else {
config = Object.assign(config, {
hotOnly: true,
disableHostCheck: true
})
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
module.exports = defineConfig({
transpileDependencies: true,
devServer:getDevServer(true)
})
vite.config.js中这么写
import getDevServer from './config/index.js'
...
{
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加速的兼容模式详解 并修改所得
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";
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}"`
}
return {
build: {
chunkSizeWarningLimit: 10000,
},
resolve: {
extensions: [".vue", ".mjs", ".js", ".ts", ".jsx", ".tsx", ".json"],
alias:{
'@': path.resolve(__dirname, './src/')
},
},
server:getDevServer(),
define,
plugins: [
createSvgIconsPlugin({
iconDirs: [path.resolve(process.cwd(), 'src/assets/svgs')],
symbolId: '[name]'
}),
createVuePlugin(),
createHtmlPlugin({
minify: true,
template: './index.html',
entry: '/src/main.ts',
inject: {
data: {
...env
}
}
})
]
}
})
package.json部分 需要class组件写法的加上 “vue-class-component”: “^7.2.3”, “vue-property-decorator”: “^9.1.2”, 可以实现class组件写法和原来的非class写法在typescript下兼容
{
"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"
]
}
|