打包工具出现要解决的问题:
1、ES Module的浏览器兼容性问题;
2、模块文件过多导致频繁发送网络请求问题;
3、资源文件模块化的问题;
Vite为什么加载那么快?
1、不需要打包,只需要加载需要的模块;
2、vue文件预先被Vite预编译为js。
3、第三方依赖或者裸模块的加载,会被预打包。
使用Vite时如何配置路径别名
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import {resolve} from 'path'
// https://vitejs.dev/config/
export default defineConfig({
resolve: {
alias: {
'@': resolve('./src'),
'comp': resolve('./src/components')
}
},
plugins: [vue()]
})
样式文件如何使用module
// 1、
<style module>
code{
background-color: #eee;
padding: 2px 4px;
border-radius: 4px;
color: red;
}
</style>
<p>
Edit
<code :class="$style.code">components/HelloWorld.vue</code> to test hot module replacement.
</p>
// 2、
// Index.module.css
.code {
background-color: #eee;
padding: 2px 4px;
border-radius: 4px;
color: red;
}
使用时首先需要导入到Vue文件中
import classes from './Index.module.css';
...
setup: () => {
const count = ref(0)
return { count, classes }
}
<p>
Edit
<code :class="classes.code">components/HelloWorld.vue</code> to test hot module replacement.
</p>
针对不同的浏览器做css hack
我们会优先使用autoprefixer来帮助我们解决问题;
安装依赖:npm i autoprefixer -D; 创建一个名为postcss.config.js的文件同时添加内容:
module.exports = {
plugins: [
require('autoprefixer')
]
}
配置代理
在 vite.config.js文件中写入配置项,配置方法和之前的一致
server: {
proxy: {
'/api': {
target: '',
changeOrigin: true,
rewrite: path => path.replace(/^/api/, '')
}
}
},
数据mock
npm i mockjs -S
npm i vite-plugin-mock -D
在 vite.config.js中配置plugin
import { viteMockServe } from 'vite-plugin-mock';
export default defineConfig({
plugins: [ viteMockServe({}) ]
})
eslint格式化配置
在package.json文件中配置devDependencies属性,添加以下依赖
"@typescript-eslint/eslint-plugin": "^4.15.2",
"@typescript-eslint/parser": "^4.15.2",
"@vue/eslint-config-prettier": "^6.0.0",
"@vue/eslint-config-typescript": "^7.0.0",
"@vuedx/typescript-plugin-vue": "^0.6.3",
"eslint": "^7.20.0",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-vue": "^7.6.0",
"prettier": "^2.2.1"
创建 .eslintrc.js 同时添加配置
module.exports = {
root: true,
env: {
browser: true,
es6: true,
node: true
},
extends: [
'plugin:vue/vue3-recommended',
'eslint:recommended',
'@vue/typescript/recommended',
'@vue/prettier',
'@vue/prettier/@typescript-eslint'
],
parserOptions: {
ecmaVersion: 2021
},
plugins: [],
rules: {
"no-unused-vars":"off",
"@typescript-eslint/no-unused-vars":"off"
}
}
同时在package.json文件中添加命令
"lint": "eslint --ext .ts,vue src/** --no-error-on-unmatched-pattern --quiet"
"lint:fix": "eslint --ext .ts,vue src/** --no-error-on-unmatched-pattern --fix"
Jest
首先需要在package.json文件中配置依赖:
"jest": "^26.6.3",
"@types/jest": "^26.0.20",
"vue-jest": "^5.0.0-alpha.7",
"babel-jest": "^26.6.3",
"@babel/preset-env": "^7.12.17",
"@vue/test-utils": "^2.0.0-beta.9",
"ts-jest": "^26.5.1",
"@babel/preset-typescript": "^7.12.17"
添加一个新的文件jest.config.js
module.exports = {
transform: {
"^.+.vue$": "vue-jest",
"^.+.jsx?$": "babel-jest",
"^.+.tsx?$": "ts-jest",
},
moduleNameMapper: {
"^@/components(.*)$": "<rootDir>/src/components$1"
},
testMatch: ["**/tests/unit/**/*.[jt]s?(x)"]
}
Vite插件的形式
export default {
name: "my-vite-plugin",
resolveId(id) {},
load(id) {},
transform(code){}
}
export default function (options) {
return {
name: "my-vite-plugin",
resolveId(id) {},
load(id) {},
transform(code){}
}
}
插件钩子
开发时,Vite创建一个插件容器按照顺序调用各个钩子
- config: 修改Vite配置
- configResolved: Vite配置确认
- configureServer: 用于配置dev server
- transformIndexHtml: 用于转换宿主页
- resolved 创建自定义确认函数,常用语定位第三方依赖
- load 创建自定义加载函数,可用于返回自定义的内容
- transform 可用于转换已加载的模块内容
- handleHotUpdate: 自定义HMR更新时调用
定义我的第一个插件
// vite-plugin-example.js
export default function (options) {
return {
name: "plugin-example", // 随便定义
resolveId(source) {
// 是否处理当前的请求
if (source === "virtual-module") {
return source; // 表示接管
}
return null;
},
load(id) {
if (id === "virtual-module") {
// 返回加载模块代码
return 'export default "this is virtual-module"';
}
return null;
},
};
}
使用时在vite.config.js中
import virtualModule from "./plugins/vite-plugin-example";
```
plugins: [vue(), virtualModule()],
```
自定义差价实例
// vite-plugin-i18n.js
export default {
// 将load进来的代码块进一步的加工处理
/**
*
* @param code 代码块的内容
* @param id 请求的URL
* @returns {string|null}
*/
transform(code, id) {
// 将i18n信息写入组件配置
if (/vue&type=i18n/.test(id)) {
return `export default Comp => {
Comp.i18n = ${code}
}`;
}
return null;
},
};
// vite-config.js
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import { resolve } from "path";
import virtualModule from "./plugins/vite-plugin-example";
import i18n from "./plugins/vite-plugin-i18n";
// https://vitejs.dev/config/
export default defineConfig({
server: {
proxy: {
"/api": {
target: "",
changeOrigin: true,
rewrite: (path) => path.replace(/^/api/, ""),
},
},
},
resolve: {
alias: {
"@": resolve("./src"),
comp: resolve("./src/components"),
},
},
plugins: [vue(), virtualModule(), i18n],
});
// App.vue
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<HelloWorld msg="Hello Vue 3 + TypeScript + Vite" />
<span>{{ t("language") }}</span>
<select v-model="locale">
<option value="zh">zh</option>
<option value="en">en</option>
</select>
<span>{{ t("hello") }}</span>
</template>
<i18n>
{
"en": {
"language": "Language",
"hello": "hello, world!"
},
"zh": {
"language": "语言",
"hello": "你好,世界!"
}
}
</i18n>
<script lang="ts">
import { defineComponent, getCurrentInstance, ref, computed } from "vue";
import HelloWorld from "./components/HelloWorld.vue";
export default defineComponent({
name: "App",
components: {
HelloWorld,
},
setup: () => {
const ins = getCurrentInstance();
function useI18n() {
const locale = ref("zh");
const i18n = ins!.type.i18n;
const t = (msg) => {
return computed(() => i18n[locale.value][msg]).value;
};
return { locale, t };
}
const { locale, t } = useI18n();
return {
locale,
t,
};
},
});
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>