Vue3学习笔记(八)—— Vite、ESLint
一、vite
1.1、概要
Vite(法语意为 "快速的",发音 /vit/
,发音同 "veet")是一种新型前端构建工具,能够显著提升前端开发体验。它主要由两部分组成:
-
一个开发服务器,它基于 原生 ES 模块 提供了 丰富的内建功能,如速度快到惊人的 模块热更新(HMR)。
-
一套构建指令,它使用 Rollup 打包你的代码,并且它是预配置的,可输出用于生产环境的高度优化过的静态资源。
- https://www.rollupjs.com/
Vite 意在提供开箱即用的配置,同时它的 插件 API 和 JavaScript API 带来了高度的可扩展性,并有完整的类型支持。
本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)
Vue 脚手架工具 vue-cli 使用 webpack 进行打包,开发时可以启动本地开发服务器,实时预览。因为需要对整个项目文件进行打包,开发服务器启动缓慢
而对于开发时文件修改后的热更新 HMR 也存在同样的问题
Webpack 的热更新会以当前修改的文件为入口重新 build 打包,所有涉及到的依赖也都会被重新加载一次
Vite 则很好地解决了上面的两个问题
打包问题
vite 只启动一台静态页面的服务器,对文件代码不打包,服务器会根据客户端的请求加载不同的模块处理,实现真正的按需加载
热更新问题
vite 采用立即编译当前修改文件的办法。同时 vite 还会使用缓存机制( http 缓存 => vite 内置缓存 ),加载更新后的文件内容
所以,vite 具有了快速冷启动、按需编译、模块热更新等优良特质
综上所述,vite 构建项目与 vue-cli 构建的项目在开发模式下还是有比较大的区别:
-
Vite 在开发模式下不需要打包可以直接运行,使用的是 ES6 的模块化加载规则;Vue-CLI 开发模式下必须对项目打包才可以运行
-
Vite 基于缓存的热更新,Vue-CLI 基于 Webpack 的热更新
1.2、使用vite构建第一个vue项目
方法一:
要使用 Vite 来创建一个 Vue 项目,非常简单:
$ npm init vue@latest
这个命令会安装和执行 create-vue,它是 Vue 提供的官方脚手架工具。跟随命令行的提示继续操作即可。
- 要学习更多关于 Vite 的知识,请查看 Vite 官方文档。
- 若要了解如何为一个 Vite 项目配置 Vue 相关的特殊行为,比如向 Vue 编译器传递相关选项,请查看 @vitejs/plugin-vue 的文档。
上面提到的两种在线演练场也支持将文件作为一个 Vite 项目下载。
方法二:
Vite 需要 Node.js 版本 14.18+,16+。然而,有些模板需要依赖更高的 Node 版本才能正常运行,当你的包管理器发出警告时,请注意升级你的 Node 版本。
使用 NPM:
$ npm create vite@latest
使用 Yarn:
$ yarn create vite
使用 PNPM:
$ pnpm create vite
code .可以使用visual studio code打开代码编辑窗口。
1.3、错误处理
1.3.1、导入自定义模块错误
vite+Ts+Vue3搭建的项目中,把Ts类型文件抽离出去,再导入到页面组件时,出现“导入路径不能以“.ts”扩展名结束”的爆红错误,但这个错误并不影响项目运行。
解决方法:
import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import path from 'path' // https://vitejs.dev/config/ export default defineConfig({ plugins: [vue()], resolve: { alias: { '@': path.resolve(__dirname, 'src') }, extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json'] } })
path.resolve() 该方法将一些的 路径/路径段 解析为绝对路径。
不能解析@的问题,修改tsconfig.json文件
{ "compilerOptions": { "target": "ESNext", "useDefineForClassFields": true, "module": "ESNext", "moduleResolution": "Node", "strict": true, "jsx": "preserve", "resolveJsonModule": true, "isolatedModules": true, "esModuleInterop": true, "lib": ["ESNext", "DOM"], "skipLibCheck": true, "noEmit": true, "baseUrl": ".", "paths": { "@/*": ["src/*"] } }, "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], "references": [{ "path": "./tsconfig.node.json" }] }
增加:
"baseUrl": ".", "paths": { "@/*": ["src/*"] }
1.3.2、导入内置模块错误
在vite.config.ts 配置 报错 找不到模块“path”或其相应的类型声明
解决方法:
npm install @types/node --save-dev
1.3.3、找不到模块“./App.vue”或其相应的类型声明。ts(2307)
解决方法:在vite-env.d.ts文件中增加以下声明:
declare module '*.vue' { import type { DefineComponent } from 'vue'; const vueComponent: DefineComponent<{}, {}, any>; export default vueComponent; }
1.4、命令与配置
开发服务器#
vite
#
在当前目录下启动 Vite 开发服务器。
使用#
vite [root]
选项#
选项 | |
---|---|
--host [host] |
指定主机名称 (string ) |
--port <port> |
指定端口 (number ) |
--https |
使用 TLS + HTTP/2 (boolean ) |
--open [path] |
启动时打开浏览器 (boolean | string ) |
--cors |
启用 CORS (boolean ) |
--strictPort |
如果指定的端口已在使用中,则退出 (boolean ) |
--force |
强制优化器忽略缓存并重新构建 (boolean ) |
-c, --config <file> |
使用指定的配置文件 (string ) |
--base <path> |
公共基础路径(默认为:/ )(string ) |
-l, --logLevel <level> |
Info | warn | error | silent (string ) |
--clearScreen |
允许或禁用打印日志时清除屏幕 (boolean ) |
--profile |
启动内置的 Node.js 调试器(查看 性能瓶颈) |
-d, --debug [feat] |
显示调试日志 (string | boolean ) |
-f, --filter <filter> |
过滤调试日志 (string ) |
-m, --mode <mode> |
设置环境模式 (string ) |
-h, --help |
显示可用的 CLI 选项 |
-v, --version |
显示版本号 |
构建#
vite build
#
构建生产版本。
使用#
vite build [root]
选项#
选项 | |
---|---|
--target <target> |
编译目标(默认为:"modules" )(string ) |
--outDir <dir> |
输出目录(默认为:dist )(string ) |
--assetsDir <dir> |
在输出目录下放置资源的目录(默认为:"assets" )(string ) |
--assetsInlineLimit <number> |
静态资源内联为 base64 编码的阈值,以字节为单位(默认为:4096 )(number ) |
--ssr [entry] |
为服务端渲染配置指定入口文件 (string ) |
--sourcemap [output] |
构建后输出 source map 文件(默认为:false )(boolean | "inline" | "hidden" ) |
--minify [minifier] |
允许或禁用最小化混淆,或指定使用哪种混淆器(默认为:"esbuild" )(boolean | "terser" | "esbuild" ) |
--manifest [name] |
构建后生成 manifest.json 文件 (boolean | string ) |
--ssrManifest [name] |
构建后生成 SSR manifest.json 文件 (boolean | string ) |
--force |
强制优化器忽略缓存并重新构建(实验性)(boolean ) |
--emptyOutDir |
若输出目录在根目录外,强制清空输出目录 (boolean ) |
-w, --watch |
在磁盘中模块发生变化时,重新构建 (boolean ) |
-c, --config <file> |
使用指定的配置文件 (string ) |
--base <path> |
公共基础路径(默认为:/ )(string ) |
-l, --logLevel <level> |
Info | warn | error | silent (string ) |
--clearScreen |
允许或禁用打印日志时清除屏幕 (boolean ) |
--profile |
启动内置的 Node.js 调试器(查看 性能瓶颈) |
-d, --debug [feat] |
显示调试日志 (string | boolean ) |
-f, --filter <filter> |
过滤调试日志 (string ) |
-m, --mode <mode> |
设置环境模式 (string ) |
-h, --help |
显示可用的 CLI 选项 |
vite 打包里如何删除代码中的console.log
在使用 Vite 进行项目构建时,如果你想要在最终的生产环境代码中删除所有的 console.log
语句,你可以通过配置 vite.config.js
文件来实现。Vite 使用 Rollup 作为其底层打包工具,因此可以通过 Rollup 的插件来完成这个任务。
一个常用的方法是使用 rollup-plugin-terser
,它是一个压缩插件,可以帮助移除或减少代码中的 console.log
语句。
安装 terser 插件
首先,你需要安装 rollup-plugin-terser
。可以通过 npm 来安装:
npm install rollup-plugin-terser --save-dev
或者,如果你使用 yarn:
yarn add rollup-plugin-terser --dev
配置 Vite
然后,在你的 vite.config.js
文件中,你需要导入这个插件并在 Rollup 配置中使用它:
import { defineConfig } from 'vite'; import { terser } from "rollup-plugin-terser"; export default defineConfig({ // ...其他配置 build: { rollupOptions: { plugins: [ terser({ compress: { drop_console: true, // 这会删除 console.* 函数的调用 }, }), ], }, }, });
在这个配置中,drop_console: true
表示在压缩过程中会删除所有的 console.*
函数调用,这包括 console.log
、console.error
等。
注意事项
- 使用此方法会移除生产环境代码中的所有控制台输出。如果你的应用依赖于
console.error
或console.warn
等用于错误处理或警告的输出,你可能需要更细致地配置这个插件,以保留这些重要的日志信息。 - 在开发环境中,
console.log
通常是有用的,因此这个配置仅应用于生产环境的构建。 - 确保测试构建后的应用,以确认删除
console.log
后应用仍然按预期工作。
其他#
vite optimize
#
预构建依赖。
vite optimize
是 Vite 中的一个特性,用于预构建依赖。这是 Vite 在 2.x 版本中引入的一项功能,目的是提升开发服务器的启动速度和模块热更新(HMR)的响应速度。
作用
-
预构建依赖:Vite 会在第一次启动时扫描你的源代码,检测出所有外部依赖(即
node_modules
中的模块),并预构建这些模块。这意味着它会提前将这些模块转换为更适合浏览器加载的格式。 -
缓存:构建结果会被缓存起来,这样在后续的启动中就不需要再次构建,从而减少了开发服务器的启动时间。
-
优化第三方库:对于那些不是专门为 ESM(ES模块)设计的第三方库,Vite 的优化可以帮助转换和整理这些库,使它们更适合在现代浏览器中运行。
例子
假设你在项目中使用了像 lodash
这样的大型第三方库。在没有优化的情况下,每当你启动开发服务器时,Vite 都需要处理这个库的大量代码,可能会导致启动缓慢。使用 vite optimize
,Vite 会在第一次启动时预构建 lodash
,将其转换成更高效的格式,并缓存起来。这样,在后续的启动中,由于已经有了预构建的缓存,服务器的启动速度会更快。
如何使用
一般情况下,你不需要手动运行 vite optimize
。Vite 会自动在需要时进行预构建。但是,在某些情况下,如果你需要强制重新预构建依赖,可以在命令行中运行这个命令。
请注意,随着 Vite 的不断发展,命令和功能可能会有所变化,所以建议查阅最新的 Vite 文档以获取最准确的信息。
使用#
vite optimize [root]
选项#
选项 | |
---|---|
--force |
强制优化器忽略缓存并重新构建 (boolean ) |
-c, --config <file> |
使用指定的配置文件 (string ) |
--base <path> |
公共基础路径(默认为:/ )(string ) |
-l, --logLevel <level> |
Info | warn | error | silent (string ) |
--clearScreen |
允许或禁用打印日志时清除屏幕 (boolean ) |
-d, --debug [feat] |
显示调试日志 (string | boolean ) |
-f, --filter <filter> |
过滤调试日志 (string ) |
-m, --mode <mode> |
设置环境模式 (string ) |
-h, --help |
显示可用的 CLI 选项 |
vite preview
#
本地预览构建产物。不要将其用作生产服务器,因为它不是为此而设计的。
vite preview
命令在 Vite 中扮演着一个非常重要的角色。它的主要作用是启动一个本地的静态文件服务器,用于预览你的项目。这个服务器通常用来模拟生产环境的行为,帮助开发者测试构建后的应用程序。
作用
-
模拟生产环境:
vite preview
会以类似于生产环境的方式来服务你的应用。这是检查你的项目在生产模式下的表现的好方法。 -
本地测试构建产物:在你运行
vite build
构建项目后,使用vite preview
可以在本地测试这些构建产物,确保构建过程中没有出现问题。 -
简单的服务器功能:这个命令提供了一个基本的静态文件服务器,不需要额外的服务器软件即可运行,非常适合快速检查和演示。
例子
假设你正在开发一个前端应用并使用 Vite 作为构建工具。你的应用现在开发完成,需要构建并检查最终的产品。以下是可能的步骤:
-
构建应用:首先,你运行
vite build
来构建你的应用。这会生成用于生产环境的静态文件,如 HTML、JavaScript、CSS 等。 -
预览应用:构建完成后,你使用
vite preview
来启动一个本地服务器。这个服务器会提供构建后的静态文件,让你能够在浏览器中预览应用。 -
检查和调试:在
vite preview
提供的服务器上,你可以检查应用的表现是否符合预期,例如加载速度、功能完整性和用户界面等。由于这个预览是在类似生产环境的设置下进行的,它有助于识别那些可能只在生产环境中出现的问题。
注意事项
vite preview
主要用于测试和验证目的,不建议用作长期的生产环境服务器。- 预览服务器通常不包含生产环境服务器的所有功能,如详细的安全设置和性能优化。
vite preview
是一个非常实用的工具,尤其是在开发周期的后期,当你需要验证你的构建产物是否正常工作时。
使用#
vite preview [root]
选项#
选项 | |
---|---|
--host [host] |
指定主机名称 (string ) |
--port <port> |
指定端口 (number ) |
--strictPort |
如果指定的端口已在使用中,则退出 (boolean ) |
--https |
使用 TLS + HTTP/2 (boolean ) |
--open [path] |
启动时打开浏览器 (boolean | string ) |
--outDir <dir> |
输出目录(默认为:dist )(string ) |
-c, --config <file> |
使用指定的配置文件 (string ) |
--base <path> |
公共基础路径(默认为:/ )(string ) |
-l, --logLevel <level> |
Info | warn | error | silent (string ) |
--clearScreen |
允许或禁用打印日志时清除屏幕 (boolean ) |
-d, --debug [feat] |
显示调试日志 (string | boolean ) |
-f, --filter <filter> |
过滤调试日志 (string ) |
-m, --mode <mode> |
设置环境模式 (string ) |
-h, --help |
显示可用的 CLI 选项 |
您提供的代码是package.json
文件中的一部分,通常用于定义npm脚本,这些脚本用于在Node.js环境中运行各种任务。下面是对每个脚本的解释:
-
"dev": "vite --mode production"
- 这个命令用于启动Vite的开发服务器,但是它使用
--mode production
选项,这意味着尽管是在开发模式下运行,但它将使用生产环境的配置。这可能是为了测试生产环境的行为。
- 这个命令用于启动Vite的开发服务器,但是它使用
-
"build": "run-p type-check "build-only {@}" --"
run-p
是npm-run-all
的一个命令,用于并行执行多个npm脚本。- 这个命令首先运行
type-check
脚本进行类型检查。 - 然后运行
build-only
脚本来构建应用程序,{@}
是一个占位符,用于传递额外的命令行参数。
-
"preview": "vite preview"
- 这个命令用于启动Vite的预览服务器,它通常用于本地预览构建的应用程序。
-
"build-only": "vite build"
- 这个脚本使用Vite构建应用程序。它是生产环境下的构建过程,会对代码进行打包和优化。
-
"type-check": "vue-tsc --noEmit -p tsconfig.app.json --composite false"
- 这个脚本使用
vue-tsc
进行类型检查,这是一个为Vue与TypeScript环境定制的TypeScript编译器。 --noEmit
选项表示编译器只进行类型检查,不产生任何输出文件。-p tsconfig.app.json
指定了使用特定的TypeScript配置文件。--composite false
可能是用于指示编译器这不是一个复合项目,或者覆盖tsconfig.app.json
中的相关设置。
- 这个脚本使用
综上所述,这些脚本提供了一个完整的工作流程,包括开发、构建、类型检查和预览应用程序的功能。
1.4.0、共享配置
Vite常用配置
{ root: process.cwd(), // 项目根目录(index.html 文件所在的位置), base: '/', // 开发或生产环境服务的公共基础路径 配置引入相对路径 mode: 'development', // 模式 plugins: [vue()], // 需要用到的插件数组 publicDir: 'public', // 静态资源服务的文件夹 cacheDir: 'node_modules/.vite', // 存储缓存文件的目录 resolve: { alias: [ // 文件系统路径别名 { find: /\/@\//, replacement: pathResolve('src') + '/' } ], dedupe: [], // 强制 Vite 始终将列出的依赖项解析为同一副本 conditions: [], // 解决程序包中 情景导出 时的其他允许条件 mainFields: [], // 解析包入口点尝试的字段列表 extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json'], // 导入时想要忽略的扩展名列表 preserveSymlinks: false, // 启用此选项会使 Vite 通过原始文件路径确定文件身份 }, css: { modules: { scopeBehaviour: 'global' | 'local', // ... }, postcss: '', // 内联的 PostCSS 配置 如果提供了该内联配置,Vite 将不会搜索其他 PostCSS 配置源 preprocessorOptions: { // css的预处理器选项 scss: { additionalData: `$injectedColor: orange;` } } }, json: { namedExports: true, // 是否支持从.json文件中进行按名导入 stringify: false, // 开启此项,导入的 JSON 会被转换为 export default JSON.parse("...") 会禁用按名导入 }, esbuild: { // 最常见的用例是自定义 JSX jsxFactory: 'h', jsxFragment: 'Fragment' }, assetsInclude: ['**/*.gltf'], // 指定额外的 picomatch 模式 作为静态资源处理 logLevel: 'info', // 调整控制台输出的级别 'info' | 'warn' | 'error' | 'silent' clearScreen: true, // 设为 false 可以避免 Vite 清屏而错过在终端中打印某些关键信息 envDir: '/', // 用于加载 .env 文件的目录 envPrefix: [], // 以 envPrefix 开头的环境变量会通过 import.meta.env 暴露在你的客户端源码中 server: { host: '127.0.0.1', // 指定服务器应该监听哪个 IP 地址 port: 5000, // 指定开发服务器端口 strictPort: true, // 若端口已被占用则会直接退出 https: false, // 启用 TLS + HTTP/2 open: true, // 启动时自动在浏览器中打开应用程序 proxy: { // 配置自定义代理规则 '/api': { target: 'http://jsonplaceholder.typicode.com', changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, '') } }, cors: true, // 配置 CORS force: true, // 强制使依赖预构建 hmr: { // 禁用或配置 HMR 连接 // ... }, watch: { // 传递给 chokidar 的文件系统监听器选项 // ... }, middlewareMode: '', // 以中间件模式创建 Vite 服务器 fs: { strict: true, // 限制为工作区 root 路径以外的文件的访问 allow: [], // 限制哪些文件可以通过 /@fs/ 路径提供服务 deny: ['.env', '.env.*', '*.{pem,crt}'], // 用于限制 Vite 开发服务器提供敏感文件的黑名单 }, origin: 'http://127.0.0.1:8080/', // 用于定义开发调试阶段生成资产的 origin }, build: { target: ['modules'], // 设置最终构建的浏览器兼容目标 polyfillModulePreload: true, // 是否自动注入 module preload 的 polyfill outDir: 'dist', // 指定输出路径 assetsDir: 'assets', // 指定生成静态文件目录 assetsInlineLimit: '4096', // 小于此阈值的导入或引用资源将内联为 base64 编码 cssCodeSplit: true, // 启用 CSS 代码拆分 cssTarget: '', // 允许用户为 CSS 的压缩设置一个不同的浏览器 target 与 build.target 一致 sourcemap: false, // 构建后是否生成 source map 文件 rollupOptions: {}, // 自定义底层的 Rollup 打包配置 lib: {}, // 构建为库 manifest: false, // 当设置为 true,构建后将会生成 manifest.json 文件 ssrManifest: false, // 构建不生成 SSR 的 manifest 文件 ssr: undefined, // 生成面向 SSR 的构建 minify: 'esbuild', // 指定使用哪种混淆器 terserOptions: {}, // 传递给 Terser 的更多 minify 选项 write: true, // 启用将构建后的文件写入磁盘 emptyOutDir: true, // 构建时清空该目录 brotliSize: true, // 启用 brotli 压缩大小报告 chunkSizeWarningLimit: 500, // chunk 大小警告的限制 watch: null, // 设置为 {} 则会启用 rollup 的监听器 }, preview: { port: 5000, // 指定开发服务器端口 strictPort: true, // 若端口已被占用则会直接退出 https: false, // 启用 TLS + HTTP/2 open: true, // 启动时自动在浏览器中打开应用程序 proxy: { // 配置自定义代理规则 '/api': { target: 'http://jsonplaceholder.typicode.com', changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, '') } }, cors: true, // 配置 CORS }, optimizeDeps: { entries: [], // 指定自定义条目——该值需要遵循 fast-glob 模式 exclude: [], // 在预构建中强制排除的依赖项 include: [], // 可强制预构建链接的包 keepNames: false, // true 可以在函数和类上保留 name 属性 }, ssr: { external: [], // 列出的是要为 SSR 强制外部化的依赖, noExternal: '', // 列出的是防止被 SSR 外部化依赖项 target: 'node', // SSR 服务器的构建目标 } }
base
- 类型:
string
- 默认:
/
开发或生产环境服务的公共基础路径。合法的值包括以下几种:
- 绝对 URL 路径名,例如
/foo/
- 完整的 URL,例如
https://foo.com/
- 空字符串或
./
(用于嵌入形式的开发)
mode
- 类型:
string
- 默认:
'development'
用于开发,'production'
用于构建
在配置中指明将会把 serve 和 build 时的模式 都 覆盖掉。也可以通过命令行 --mode
选项来重写。
main.ts中使用console.log(import.meta.env);查看
envDir
- 类型:
string
- 默认:
root
用于加载 .env
文件的目录。可以是一个绝对路径,也可以是相对于项目根的路径。
关于环境文件的更多信息,请参见 这里。
在 Vite 配置文件中,envDir
选项用于指定环境变量文件(例如 .env
文件)的存放位置。默认情况下,Vite 会在项目的根目录中查找 .env
文件。通过设置 envDir
,你可以自定义环境变量文件的存放目录,使项目结构更加清晰和组织化。
作用
- 自定义环境变量文件位置:允许你将
.env
文件放在项目的特定目录下,而不是项目的根目录。 - 项目结构组织:有助于在项目中维护清晰的结构,特别是在大型项目中,可以将配置文件集中管理。
示例
假设你有一个 Vite 项目,你希望将所有的环境变量文件放在项目的 config
目录下,而不是根目录。你可以在 Vite 的配置文件(如 vite.config.js
或 vite.config.ts
)中这样设置:
import { defineConfig } from 'vite'; import path from 'path'; export default defineConfig({ envDir: path.resolve(__dirname, 'config') });
这个设置意味着 Vite 会在 config
目录下查找 .env
文件,而不是在项目的根目录。这样,如果你有如下的目录结构:
/your-project
|--/config
|--.env.development
|--.env.production
|--/src
|--vite.config.js
当你运行 Vite 开发服务器或构建命令时,Vite 会根据当前的模式(开发或生产)加载 config
目录下相应的 .env
文件。
注意事项
- 确保在设置
envDir
后,相应的环境变量文件确实存在于你指定的目录中。 - 这种做法有助于在多环境项目中维护清晰的环境配置,使得环境变量的管理更加直观和高效。
.env
文件
Vite 使用 dotenv 从你的 环境目录 中的下列文件加载额外的环境变量:
.env # 所有情况下都会加载
.env.local # 所有情况下都会加载,但会被 git 忽略
.env.[mode] # 只在指定模式下加载
.env.[mode].local # 只在指定模式下加载,但会被 git 忽略
环境加载优先级
一份用于指定模式的文件(例如 .env.production
)会比通用形式的优先级更高(例如 .env
)。
另外,Vite 执行时已经存在的环境变量有最高的优先级,不会被 .env
类文件覆盖。例如当运行 VITE_SOME_KEY=123 vite build
的时候。
.env
类文件会在 Vite 启动一开始时被加载,而改动会在重启服务器后生效。
加载的环境变量也会通过 import.meta.env
以字符串形式暴露给客户端源码。
为了防止意外地将一些环境变量泄漏到客户端,只有以 VITE_
为前缀的变量才会暴露给经过 vite 处理的代码。例如下面这些环境变量:
VITE_SOME_KEY=123
DB_PASSWORD=foobar
只有 VITE_SOME_KEY
会被暴露为 import.meta.env.VITE_SOME_KEY
提供给客户端源码,而 DB_PASSWORD
则不会。
console.log(import.meta.env.VITE_SOME_KEY) // 123
console.log(import.meta.env.DB_PASSWORD) // undefined
此外,Vite 使用 dotenv-expand 来直接拓展变量。想要了解更多相关语法,请查看 它们的文档。
请注意,如果想要在环境变量中使用 $
符号,则必须使用 \
对其进行转义。
KEY=123
NEW_KEY1=test$foo # test
NEW_KEY2=test\$foo # test$foo
NEW_KEY3=test$KEY # test123
如果你想自定义 env 变量的前缀,请参阅 envPrefix。
安全注意事项
-
.env.*.local
文件应是本地的,可以包含敏感变量。你应该将.local
添加到你的.gitignore
中,以避免它们被 git 检入。 -
由于任何暴露给 Vite 源码的变量最终都将出现在客户端包中,
VITE_*
变量应该不包含任何敏感信息。
1.4.1、主机与端口配置
server.host
- 类型:
string | boolean
- 默认:
'localhost'
指定服务器应该监听哪个 IP 地址。 如果将此设置为 0.0.0.0
或者 true
将监听所有地址,包括局域网和公网地址。
也可以通过 CLI 使用 --host 0.0.0.0
或 --host
来设置。
server.port
- 类型:
number
- 默认值:
5173
指定开发服务器端口。注意:如果端口已经被使用,Vite 会自动尝试下一个可用的端口,所以这可能不是开发服务器最终监听的实际端口。
server.strictPort
- 类型:
boolean
设为 true
时若端口已被占用则会直接退出,而不是尝试下一个可用端口。
测试无效,端口被占用启动不了服务器监听程序。
1.4.2、HTTPS
超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可以直接读懂其中的信息,因此,HTTP协议不适合传输一些敏感信息,比如:信用卡号、密码等支付信息。
为了解决HTTP协议的这一缺陷,需要使用另一种协议:安全套接字层超文本传输协议HTTPS,为了数据传输的安全,HTTPS在HTTP的基础上加入了SSL/TLS协议,SSL/TLS依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。
HTTPS协议是由SSL/TLS+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全
HTTPS协议的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。
HTTPS和HTTP的主要区别
1、https协议需要到CA申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl/tls加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL/TLS+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
npm i mkcert
生成ca证书
cd [project folder]
mkdir keys
cd keys
mkcert create-ca
再根据ca证书生成cert证书
# mkcert create-cert [options] # options 参见npm文档
# 如下,设置domains
mkcert create-cert --domains 127.0.0.1,localhost,custom1.domain.xxx,custom2.domain.xxx
安装证书
修改vite.config文件
https: { cert: fs.readFileSync(path.join(__dirname, 'keys/cert.crt')), key: fs.readFileSync(path.join(__dirname, 'keys/cert.key')), },
@vitejs/plugin-basic-ssl
另一个方案比较适用的方案,就是自己本地生成证书,并且让浏览器或者系统信任本地证书,项目内进行简单的配置就可以实现访问 https://localhost
. 生成证书工具可以借助 mkcert 或者 openssl
Vite 项目
Vite 项目可以使用官方插件 @vitejs/plugin-basic-ssl, 已经帮你生成好了证书,直接引入该插件即可。
// vite.config.js
import basicSsl from '@vitejs/plugin-basic-ssl'
export default {
plugins: [
basicSsl()
]
}
复制代码
启动服务后访问 https://localhost:5173
即可。
1.4.3、自动打开浏览器
server.open
- 类型:
boolean | string
在开发服务器启动时自动在浏览器中打开应用程序。当此值为字符串时,会被用作 URL
的路径名。若你想指定喜欢的浏览器打开服务器,你可以设置环境变量 process.env.BROWSER
(例如:firefox
)。查看 这个 open
包 获取更多细节。
示例:
export default defineConfig({
server: {
open: '/docs/index.html'
}
})
1.4.4、别名
resolve.alias
- 类型:
Record<string, string> | Array<{ find: string | RegExp, replacement: string, customResolver?: ResolverFunction | ResolverObject }>
将会被传递到 @rollup/plugin-alias
作为 entries 的选项。也可以是一个对象,或一个 { find, replacement, customResolver
}
的数组。
当使用文件系统路径的别名时,请始终使用绝对路径。相对路径的别名值会原封不动地被使用,因此无法被正常解析。
报错描述:import path from ‘path’ 有波浪线警告解决办法
报错原因:node下的api不能识别到path这个东西,需要安装@types/node
解决办法:npm install @types/node -D
更高级的自定义解析方法可以通过 插件 实现。
resolve: { alias: { '@': path.resolve(__dirname, 'src'), '/com':path.resolve(__dirname,'src/components') }, extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json'] },
import { defineConfig, loadEnv } from 'vite' import path from 'path' import { fileURLToPath, URL } from 'node:url' // https://vitejs.dev/config/ export default defineConfig(({ mode}) => { const env = loadEnv(mode, __dirname); // 根据 mode 来判断当前是何种环境 return { resolve:{ alias: { // 第一种方式(最简洁) '@': path.resolve(__dirname, './src'), // 第二种方式 '@style': fileURLToPath(new URL('./src/assets/style', import.meta.url)), '@images': fileURLToPath(new URL('./src/assets/images', import.meta.url)), }, // 导入时想要省略的扩展名列表。 vite官方不建议忽略自定义导入类型的扩展名(例如:.vue),因为它会影响 IDE 和类型支持。 extensions: ['.mjs', '.js', '.mts', '.ts', '.jsx', '.tsx', '.json'] } } })
1.4.5、SCSS
css直接支持
sass无需配置vite,直接安装即可直接使用
npm i sass -D
如果想全局引用可以做如下配置:
src/assets/scss/global.scss
$maincolor:#00f;
vite.config
css: { preprocessorOptions:{ scss:{ additionalData:`@import "@/assets/scss/global.scss";` } } }
Counter.vue
<style lang="scss" scoped> $bgcolor: #dfe; .cls1 { background: $bgcolor; color: $maincolor; } </style>
运行
1.4.6、less
less无需配置vite,直接安装即可直接使用
npm i less -D
如果想全局引用可以做如下配置:
src/assets/less/global.less
@mycolor:#f00;
vite.config
css: { preprocessorOptions:{ scss:{ additionalData:`@import "@/assets/scss/global.scss";` }, less:{ additionalData:`@import "@/assets/less/global.less";` } } }
Counter.vue
<style lang="less" scoped> @bgcolor: #fde; .cls1 { background: @bgcolor; color: @mycolor; } </style>
运行:
1.4.7、设置最终构建的浏览器兼容目标
??与||的区别
let c=1; //或运算如果为0,null,undefined,false,""则取表达式2的值,否则取表达式1的值
let v=c||2;
console.log(v);
let e=null; //??如果第1个表达式的值为undefined,null则取表达式2的值,否则取表达式1的值
let f=e??3;
console.log(f);
let g=c??4;
console.log(g);
都可以使用?:表达式替代
build.target
- 类型:
string | string[]
- 默认:
'modules'
- 相关内容: 浏览器兼容性
设置最终构建的浏览器兼容目标。默认值是一个 Vite 特有的值——'modules'
,这是指 支持原生 ES 模块、原生 ESM
动态导入 和 import.meta
的浏览器。
另一个特殊值是 “esnext” —— 即假设有原生动态导入支持,并且将会转译得尽可能小:
- 如果
build.minify
选项为'terser'
,'esnext'
将会强制降级为'es2019'
。 - 其他情况下将完全不会执行转译。
转换过程将会由 esbuild 执行,并且此值应该是一个合法的 esbuild 目标选项。自定义目标也可以是一个 ES
版本(例如:es2015
)、一个浏览器版本(例如:chrome58
)或是多个目标组成的一个数组。
注意:如果代码包含不能被 esbuild
安全地编译的特性,那么构建将会失败。查看 esbuild
文档 获取更多细节。
<template> <div class="cls1"> <input v-model="_name" /> {{ yourname }} </div> </template> <script lang="ts"> import { computed, ref } from "vue"; export default { setup() { let _name = ref(""); let yourname = computed({ get() { return _name.value; }, set(value) { _name.value = value ?? "Hello ES2020!"; }, }); return { yourname, _name }; }, }; </script> <style lang="less" scoped> @bgcolor: #fde; .cls1 { background: @bgcolor; color: @mycolor; } </style>
1.4.8、指定输出路径
build.outDir
- 类型:
string
- 默认:
dist
指定输出路径(相对于 项目根目录).
1.4.9、静态资源目录
build.assetsDir
- 类型:
string
- 默认:
assets
指定生成静态资源的存放路径(相对于 build.outDir
)。
1.4.10、内联资源大小限定
build.assetsInlineLimit
- 类型:
number
- 默认:
4096
(4kb)
小于此阈值的导入或引用资源将内联为 base64 编码,以避免额外的 http 请求。设置为 0
可以完全禁用此项。
Git LFS 占位符会自动排除在内联之外,因为它们不包含它们所表示的文件的内容。
1.4.11、拆分CSS代码
build.cssCodeSplit
- 类型:
boolean
- 默认:
true
启用/禁用 CSS 代码拆分。当启用时,在异步 chunk 中导入的 CSS 将内联到异步 chunk 本身,并在其被加载时插入。
如果禁用,整个项目中的所有 CSS 将被提取到一个 CSS 文件中。
1.4.12、压缩空间
build.minify
- 类型:
boolean | 'terser' | 'esbuild'
- 默认:
'esbuild'
设置为 false
可以禁用最小化混淆,或是用来指定使用哪种混淆器。默认为 Esbuild,它比 terser 快 20-40 倍,压缩率只差 1%-2%。Benchmarks
注意,在 lib 模式下使用 'es'
时,build.minify
选项不会缩减空格,因为会移除掉 pure 标注,导致破坏
tree-shaking。
当设置为 'terser'
时必须先安装 Terser。
npm add -D terser
选项 | |
---|---|
--target <target> |
编译目标(默认为:"modules" )(string ) |
--outDir <dir> |
输出目录(默认为:dist )(string ) |
--assetsDir <dir> |
在输出目录下放置资源的目录(默认为:"assets" )(string ) |
--assetsInlineLimit <number> |
静态资源内联为 base64 编码的阈值,以字节为单位(默认为:4096 )(number ) |
--ssr [entry] |
为服务端渲染配置指定入口文件 (string ) |
--sourcemap |
构建后输出 source map 文件(默认为:false )(boolean ) |
--minify [minifier] |
允许或禁用最小化混淆,或指定使用哪种混淆器(默认为:"esbuild" )(boolean | "terser" | "esbuild" ) |
--manifest [name] |
构建后生成 manifest.json 文件 (boolean | string ) |
--ssrManifest [name] |
构建后生成 SSR manifest.json 文件 (boolean | string ) |
--force |
强制优化器忽略缓存并重新构建(实验性)(boolean ) |
--emptyOutDir |
若输出目录在根目录外,强制清空输出目录 (boolean ) |
-w, --watch |
在磁盘中模块发生变化时,重新构建 (boolean ) |
-c, --config <file> |
使用指定的配置文件 (string ) |
--base <path> |
公共基础路径(默认为:/ )(string ) |
-l, --logLevel <level> |
Info | warn | error | silent (string ) |
--clearScreen |
允许或禁用打印日志时清除屏幕 (boolean ) |
-d, --debug [feat] |
显示调试日志 (string | boolean ) |
-f, --filter <filter> |
过滤调试日志 (string ) |
-m, --mode <mode> |
设置环境模式 (string ) |
-h, --help |
显示可用的 CLI 选项 |
1.4.13、预览
你可以运行 npm run build
命令来执行应用的构建。
$ npm run build
默认情况下,构建会输出到 dist
文件夹中。你可以部署这个 dist
文件夹到任何你喜欢的平台。
本地测试应用
当你构建完成应用后,你可以通过运行 npm run preview
命令,在本地测试该应用。
$ npm run build
$ npm run preview
vite preview
命令会在本地启动一个静态 Web 服务器,将 dist
文件夹运行在 http://localhost:4173
。这样在本地环境下查看该构建产物是否正常可用就方便多了。
你可以通过 --port
参数来配置服务的运行端口。
{
"scripts": {
"preview": "vite preview --port 8080"
}
}
现在 preview
命令会将服务器运行在 http://localhost:8080
。
选项 | |
---|---|
--host [host] |
指定主机名称 (string ) |
--port <port> |
指定端口 (number ) |
--strictPort |
如果指定的端口已在使用中,则退出 (boolean ) |
--https |
使用 TLS + HTTP/2 (boolean ) |
--open [path] |
启动时打开浏览器 (boolean | string ) |
--outDir <dir> |
输出目录(默认为:dist )(string ) |
-c, --config <file> |
使用指定的配置文件 (string ) |
--base <path> |
公共基础路径(默认为:/ )(string ) |
-l, --logLevel <level> |
Info | warn | error | silent (string ) |
--clearScreen |
允许或禁用打印日志时清除屏幕 (boolean ) |
-d, --debug [feat] |
显示调试日志 (string | boolean ) |
-f, --filter <filter> |
过滤调试日志 (string ) |
-m, --mode <mode> |
设置环境模式 (string ) |
-h, --help |
显示可用的 CLI 选项 |
preview.host
- 类型:
string | boolean
- 默认:
server.host
为开发服务器指定 ip 地址。 设置为 0.0.0.0
或 true
会监听所有地址,包括局域网和公共地址。
还可以通过 CLI 进行设置,使用 --host 0.0.0.0
或 --host
。
注意
在某些情况下,可能响应的是其他服务器而不是 Vite。 查看 server.host
了解更多细节。
preview.port
- 类型:
number
- 默认:
4173
指定开发服务器端口。注意,如果设置的端口已被使用,Vite 将自动尝试下一个可用端口,所以这可能不是最终监听的服务器端口。
示例:
export default defineConfig({
server: {
port: 3030
},
preview: {
port: 8080
}
})
preview.strictPort
- 类型:
boolean
- 默认:
server.strictPort
设置为 true
时,如果端口已被使用,则直接退出,而不会再进行后续端口的尝试。
preview.https
- 类型:
boolean | https.ServerOptions
- 默认:
server.https
启用 TLS + HTTP/2。注意,只有在与 server.proxy
选项 同时使用时,才会降级为
TLS。
该值也可以传递给 https.createServer()
的 options 对象。
preview.open
- 类型:
boolean | string
- 默认:
server.open
开发服务器启动时,自动在浏览器中打开应用程序。当该值为字符串时,它将被用作 URL
的路径名。如果你想在你喜欢的某个浏览器打开该开发服务器,你可以设置环境变量 process.env.BROWSER
(例如 firefox
)。欲了解更多细节,请参阅 open
包的源码。
preview.proxy
- 类型:
Record<string, string | ProxyOptions>
- 默认:
server.proxy
为开发服务器配置自定义代理规则。其值的结构为 { key: options }
的对象。如果 key
以 ^
开头,它将被识别为 RegExp
,其中 configure
选项可用于访问代理实例。
基于 http-proxy
实现,完整的参数列表参见 此链接。
preview.cors
- 类型:
boolean | CorsOptions
- 默认:
server.cors
为开发服务器配置 CORS。此功能默认启用并支持任何来源。可传递一个 options 对象 来进行配置,或者传递 false
来禁用此行为。
1.4.14、使用插件
Vite 可以使用插件进行扩展,这得益于 Rollup 优秀的插件接口设计和一部分 Vite 独有的额外选项。这意味着 Vite 用户可以利用 Rollup 插件的强大生态系统,同时根据需要也能够扩展开发服务器和 SSR 功能。
添加一个插件
若要使用一个插件,需要将它添加到项目的 devDependencies
并在 vite.config.js
配置文件中的 plugins
数组中引入它。例如,要想为传统浏览器提供支持,可以按下面这样使用官方插件 @vitejs/plugin-legacy:
$ npm add -D @vitejs/plugin-legacy
// vite.config.js
import legacy from '@vitejs/plugin-legacy'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
legacy({
targets: ['defaults', 'not IE 11'],
}),
],
})
plugins
也可以接受包含多个插件作为单个元素的预设。这对于使用多个插件实现的复杂特性(如框架集成)很有用。该数组将在内部被扁平化。
Falsy 虚值的插件将被忽略,可以用来轻松地启用或停用插件。
什么是polyfill
简单来说,polyfill就是兼容旧浏览器的代码块,磨平差异。比如说 有的浏览器不支持 globalThis
, 那我们可以自己实现一个globalThis然后注入到script中
注意:polyfill
和代码编译(renderLegacyChunks)
是两个概念, 前者是添加额外的代码来使得旧浏览器支持某些特性,后者是把浏览器不认识的语法转化为可以运行的语法
vite的polyfill分为 modern polyfill
(modernPolyfills属性)和 legacy polyfill
(polyfills属性),之所以区分开来,是为了尽量减少polyfills的大小
targets
设置目标浏览器兼容的范围。
- 类型:string|string[]|{[key: string]: string}
- 默认值:defaults
如果显式设置,则将其传递给@babel/preset-env。该选项与Browserslist 兼容。默认值:defaults,是 Browserslist 推荐的值。
defaults | Browserslist 的默认浏览器(> 0.5%,last 2 versions,Firefox ESR,not dead)。 |
dead | 没有官方支持或更新的浏览器 24 个月。现在它是IE 11, IE_Mob 11, BlackBerry 10, BlackBerry 7, Samsung 4 和 OperaMobile 12.1,所有版本的 Baidu 浏览器。 |
not ie <= 8 | 从以前的查询中排除 IE 8 及更低版本。 |
按使用统计 |
|
最新版本 |
|
浏览器版本 |
|
Node.js 版本 |
|
extends browserslist-config-mycompany | 从 browserslist-config-mycompanynpm 包中获取查询。 |
supports es6-module | 支持特定功能的浏览器。es6-module 这是 Can I Use 页面 feat 的 URL 中的参数。可以在 caniuse-lite/data/features 找到所有可用功能的列表。 |
browserslist config | Browserslist 配置中定义的浏览器。在差异服务中很有用,可以修改用户的配置,例如 browserslist config and supports es6-module. |
since 2015or last 2 years | 自 2015 年以来发布的所有版本(也since 2015-03和since 2015-03-10)。 |
unreleased versions或unreleased Chrome versions | alpha 和 beta 版本。 |
在项目根目录中,查询选择了哪些浏览器。
npx browserslist
查找插件
Vite 旨在为常见的 Web 开发范式提供开箱即用的支持。在寻找一个 Vite 或兼容的 Rollup 插件之前,请先查看 功能指引。大量在 Rollup 项目中需要使用插件的用例在 Vite 中已经覆盖到了。
查看 Plugins 章节 获取官方插件信息。社区插件列表请参见 awesome-vite。而对于兼容的 Rollup 插件,请查看 Vite Rollup 插件 获取一个带使用说明的兼容 Rollup 官方插件列表,若列表中没有找到,则请参阅 Rollup 插件兼容性章节。
你也可以使用此 npm Vite 插件搜索链接 来找到一些遵循了 推荐约定 的 Vite 插件,或者通过 npm Rollup 插件搜索链接 获取 Rollup 插件。
vite-plugin-html
https://github.com/vbenjs/vite-plugin-html/blob/main/README.zh_CN.md
功能
- HTML 压缩能力
- EJS 模版能力
- 多页应用支持
- 支持自定义
entry
- 支持自定义
template
安装 (yarn or npm)
node version: >=12.0.0
vite version: >=2.0.0
yarn add vite-plugin-html -D
或
npm i vite-plugin-html -D
使用
- 在
index.html
中增加 EJS 标签,例如
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title><%- title %></title>
<%- injectScript %>
</head>
- 在
vite.config.ts
中配置,该方式可以按需引入需要的功能即可
import { defineConfig, Plugin } from 'vite'
import vue from '@vitejs/plugin-vue'
import { createHtmlPlugin } from 'vite-plugin-html'
export default defineConfig({
plugins: [
vue(),
createHtmlPlugin({
minify: true,
/**
* 在这里写entry后,你将不需要在`index.html`内添加 script 标签,原有标签需要删除
* @default src/main.ts
*/
entry: 'src/main.ts',
/**
* 如果你想将 `index.html`存放在指定文件夹,可以修改它,否则不需要配置
* @default index.html
*/
template: 'public/index.html',
/**
* 需要注入 index.html ejs 模版的数据
*/
inject: {
data: {
title: 'index',
injectScript: `<script src="./inject.js"></script>`,
},
tags: [
{
injectTo: 'body-prepend',
tag: 'div',
attrs: {
id: 'tag',
},
},
],
},
}),
],
})
多页应用配置
import { defineConfig } from 'vite'
import { createHtmlPlugin } from 'vite-plugin-html'
export default defineConfig({
plugins: [
createHtmlPlugin({
minify: true,
pages: [
{
entry: 'src/main.ts',
filename: 'index.html',
template: 'public/index.html',
injectOptions: {
data: {
title: 'index',
injectScript: `<script src="./inject.js"></script>`,
},
tags: [
{
injectTo: 'body-prepend',
tag: 'div',
attrs: {
id: 'tag1',
},
},
],
},
},
{
entry: 'src/other-main.ts',
filename: 'other.html',
template: 'public/other.html',
injectOptions: {
data: {
title: 'other page',
injectScript: `<script src="./inject.js"></script>`,
},
tags: [
{
injectTo: 'body-prepend',
tag: 'div',
attrs: {
id: 'tag2',
},
},
],
},
},
],
}),
],
})
参数说明
createHtmlPlugin(options: UserOptions)
UserOptions
参数 | 类型 | 默认值 | 说明 |
---|---|---|---|
entry | string |
src/main.ts |
入口文件 |
template | string |
index.html |
模板的相对路径 |
inject | InjectOptions |
- | 注入 HTML 的数据 |
minify | boolean|MinifyOptions |
- | 是否压缩 html |
pages | PageOption |
- | 多页配置 |
InjectOptions
参数 | 类型 | 默认值 | 说明 |
---|---|---|---|
data | Record<string, any> |
- | 注入的数据 |
ejsOptions | EJSOptions |
- | ejs 配置项EJSOptions |
tags | HtmlTagDescriptor |
- | 需要注入的标签列表 |
data
可以在 html
中使用 ejs
模版语法获取
env 注入
默认会向 index.html 注入 .env
文件的内容,类似 vite 的 loadEnv
函数
PageOption
参数 | 类型 | 默认值 | 说明 |
---|---|---|---|
filename | string |
- | html 文件名 |
template | string |
index.html |
模板的相对路径 |
entry | string |
src/main.ts |
入口文件 |
injectOptions | InjectOptions |
- | 注入 HTML 的数据 |
MinifyOptions
默认压缩配置
collapseWhitespace: true,
keepClosingSlash: true,
removeComments: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
useShortDoctype: true,
minifyCSS: true,
运行示例
pnpm install
# spa
cd ./packages/playground/basic
pnpm run dev
# map
cd ./packages/playground/mpa
pnpm run dev
1.4.15、CSS Modules
任何以 .module.css
为后缀名的 CSS 文件都被认为是一个 CSS modules 文件。导入这样的文件会返回一个相应的模块对象:
/* example.module.css */
.red {
color: red;
}
import classes from './example.module.css'
document.getElementById('foo').className = classes.red
CSS modules 行为可以通过 css.modules
选项 进行配置。
如果 css.modules.localsConvention
设置开启了 camelCase 格式变量名转换(例如 localsConvention: 'camelCaseOnly'
),你还可以使用按名导入。
// .apply-color -> applyColor
import { applyColor } from './example.module.css'
document.getElementById('foo').className = applyColor
<template> <div> <h2 id="title">Home - 首页</h2> <button @click="setcolor">设置文字为红色</button> </div> </template> <script lang="ts" setup> import mycss from "../assets/css/home.module.css"; function setcolor() { document.getElementById("title")!.className = mycss.red; } </script> <style scoped></style>
home.module.css
.red{ color:red; } .font-color{ color:blue; background: #def; }
1.4.16、禁用 CSS 注入页面
自动注入 CSS 内容的行为可以通过 ?inline
参数来关闭。在关闭时,被处理过的 CSS 字符串将会作为该模块的默认导出,但样式并没有被注入到页面中。
import './foo.css' // 样式将会注入页面
import otherStyles from './bar.css?inline' // 样式不会注入页面
1.4.17、静态资源处理
导入一个静态资源会返回解析后的 URL:
import imgUrl from './img.png'
document.getElementById('hero-img').src = imgUrl
添加一些特殊的查询参数可以更改资源被引入的方式:
// 显式加载资源为一个 URL
import assetAsURL from './asset.js?url'
// 以字符串形式加载资源
import assetAsString from './shader.glsl?raw'
// 加载为 Web Worker
import Worker from './worker.js?worker'
// 在构建时 Web Worker 内联为 base64 字符串
import InlineWorker from './worker.js?worker&inline'
二、ESLint
2.1、概要
eslint 属于一种 QA(Quality Assurance)工具,是一个 ECMAScript/JavaScript 语法规则和代码风格的检查工具,可以用来保证写出语法正确、风格统一的代码。
eslint 完全可配置,它的目标是提供一个插件化的 javascript 代码检测工具。这意味着您可以关闭每个规则,只能使用基本语法验证,或者混合并匹配捆绑的规则和自定义规则,使 eslint 完美的适用于当前项目。
目标:能够知道 ESLint 常见的 语法规则 ,并在实际开发中遵守这些规则
官方概念:ESLint 是可组装的 JavaScript 和 JSX 检查工具。
通俗理解:一个代码 格式 的检查 工具 ,用来 约束 团队成员的 代码风格 。
好处 :
保证团队协作开发时,编写出来的 代码风格 保持一致。例如:
① 函数名和括号之间要有一个空格
② JS 中的字符串,统一使用 单引号 表示
③ 一行代码结束加不加 分号
④ 不允许 出现 ≥2 个 的连续空行
⑤ import
必须放到文件的最上面
⑥ 文件结尾要 留一行空行
⑦ 对象的末尾不要有多余的 逗号
官网:https://zh-hans.eslint.org/
源码:https://github.com/eslint/eslint
[ESLint 中文官方网站]:http://eslint.cn/
中文文档:https://zh-hans.eslint.org/docs/latest/
2.2、第一个ESLint项目
前提条件:内置 SSL 支持的 Node.js 版本(^12.22.0
、^14.17.0
或 >=16.0.0
),如果你使用的是官方
Node.js 发行版,那么已经内置了 SSL 支持。
你可以使用该命令安装并配置 ESLint:
npm init @eslint/config
注意:使用 npm init @eslint/config
时,运行目录需要已经有 package.json
文件了。如果还没有该文件,请确保在此之前运行 npm init
或 yarn init
。
在此之后,你可以像这样使用 ESLint 检查任一文件或目录:
npx eslint yourfile.js
# 或
yarn run eslint yourfile.js
也可以全局安装 ESLint 而不仅限于本地(使用 npm install eslint --global
)。但并不推荐这样做,因为无论使用哪种安装方式,你都需要在本地安装插件和可共享配置。
1、创建一个空项目、初始化为node项目
2、配置ESLint项目
3、创建index.js文件
for(var i=0;i<100;i--){}
注意这里故意把i++写成了i--,代码块中没有内容。
4、执行eslint检查
发现了2个错误
2.3、常见错误与问题
ESLint完整规则(rules)地址:https://eslint.org/docs/rules/
规则解释一:
"no-alert": 0,//禁止使用alert confirm prompt "no-array-constructor": 2,//禁止使用数组构造器 "no-bitwise": 0,//禁止使用按位运算符 "no-caller": 1,//禁止使用arguments.caller或arguments.callee "no-catch-shadow": 2,//禁止catch子句参数与外部作用域变量同名 "no-class-assign": 2,//禁止给类赋值 "no-cond-assign": 2,//禁止在条件表达式中使用赋值语句 "no-console": 2,//禁止使用console "no-const-assign": 2,//禁止修改const声明的变量 "no-constant-condition": 2,//禁止在条件中使用常量表达式 if(true) if(1) "no-continue": 0,//禁止使用continue "no-control-regex": 2,//禁止在正则表达式中使用控制字符 "no-debugger": 2,//禁止使用debugger "no-delete-var": 2,//不能对var声明的变量使用delete操作符 "no-div-regex": 1,//不能使用看起来像除法的正则表达式/=foo/ "no-dupe-keys": 2,//在创建对象字面量时不允许键重复 {a:1,a:1} "no-dupe-args": 2,//函数参数不能重复 "no-duplicate-case": 2,//switch中的case标签不能重复 "no-else-return": 2,//如果if语句里面有return,后面不能跟else语句 "no-empty": 2,//块语句中的内容不能为空 "no-empty-character-class": 2,//正则表达式中的[]内容不能为空 "no-empty-label": 2,//禁止使用空label "no-eq-null": 2,//禁止对null使用==或!=运算符 "no-eval": 1,//禁止使用eval "no-ex-assign": 2,//禁止给catch语句中的异常参数赋值 "no-extend-native": 2,//禁止扩展native对象 "no-extra-bind": 2,//禁止不必要的函数绑定 "no-extra-boolean-cast": 2,//禁止不必要的bool转换 "no-extra-parens": 2,//禁止非必要的括号 "no-extra-semi": 2,//禁止多余的冒号 "no-fallthrough": 1,//禁止switch穿透 "no-floating-decimal": 2,//禁止省略浮点数中的0 .5 3. "no-func-assign": 2,//禁止重复的函数声明 "no-implicit-coercion": 1,//禁止隐式转换 "no-implied-eval": 2,//禁止使用隐式eval "no-inline-comments": 0,//禁止行内备注 "no-inner-declarations": [2, "functions"],//禁止在块语句中使用声明(变量或函数) "no-invalid-regexp": 2,//禁止无效的正则表达式 "no-invalid-this": 2,//禁止无效的this,只能用在构造器,类,对象字面量 "no-irregular-whitespace": 2,//不能有不规则的空格 "no-iterator": 2,//禁止使用__iterator__ 属性 "no-label-var": 2,//label名不能与var声明的变量名相同 "no-labels": 2,//禁止标签声明 "no-lone-blocks": 2,//禁止不必要的嵌套块 "no-lonely-if": 2,//禁止else语句内只有if语句 "no-loop-func": 1,//禁止在循环中使用函数(如果没有引用外部变量不形成闭包就可以) "no-mixed-requires": [0, false],//声明时不能混用声明类型 "no-mixed-spaces-and-tabs": [2, false],//禁止混用tab和空格 "linebreak-style": [0, "windows"],//换行风格 "no-multi-spaces": 1,//不能用多余的空格 "no-multi-str": 2,//字符串不能用\换行 "no-multiple-empty-lines": [1, {"max": 2}],//空行最多不能超过2行 "no-native-reassign": 2,//不能重写native对象 "no-negated-in-lhs": 2,//in 操作符的左边不能有! "no-nested-ternary": 0,//禁止使用嵌套的三目运算 "no-new": 1,//禁止在使用new构造一个实例后不赋值 "no-new-func": 1,//禁止使用new Function "no-new-object": 2,//禁止使用new Object() "no-new-require": 2,//禁止使用new require "no-new-wrappers": 2,//禁止使用new创建包装实例,new String new Boolean new Number "no-obj-calls": 2,//不能调用内置的全局对象,比如Math() JSON() "no-octal": 2,//禁止使用八进制数字 "no-octal-escape": 2,//禁止使用八进制转义序列 "no-param-reassign": 2,//禁止给参数重新赋值 "no-path-concat": 0,//node中不能使用__dirname或__filename做路径拼接 "no-plusplus": 0,//禁止使用++,-- "no-process-env": 0,//禁止使用process.env "no-process-exit": 0,//禁止使用process.exit() "no-proto": 2,//禁止使用__proto__属性 "no-redeclare": 2,//禁止重复声明变量 "no-regex-spaces": 2,//禁止在正则表达式字面量中使用多个空格 /foo bar/ "no-restricted-modules": 0,//如果禁用了指定模块,使用就会报错 "no-return-assign": 1,//return 语句中不能有赋值表达式 "no-script-url": 0,//禁止使用javascript:void(0) "no-self-compare": 2,//不能比较自身 "no-sequences": 0,//禁止使用逗号运算符 "no-shadow": 2,//外部作用域中的变量不能与它所包含的作用域中的变量或参数同名 "no-shadow-restricted-names": 2,//严格模式中规定的限制标识符不能作为声明时的变量名使用 "no-spaced-func": 2,//函数调用时 函数名与()之间不能有空格 "no-sparse-arrays": 2,//禁止稀疏数组, [1,,2] "no-sync": 0,//nodejs 禁止同步方法 "no-ternary": 0,//禁止使用三目运算符 "no-trailing-spaces": 1,//一行结束后面不要有空格 "no-this-before-super": 0,//在调用super()之前不能使用this或super "no-throw-literal": 2,//禁止抛出字面量错误 throw "error"; "no-undef": 1,//不能有未定义的变量 "no-undef-init": 2,//变量初始化时不能直接给它赋值为undefined "no-undefined": 2,//不能使用undefined "no-unexpected-multiline": 2,//避免多行表达式 "no-underscore-dangle": 1,//标识符不能以_开头或结尾 "no-unneeded-ternary": 2,//禁止不必要的嵌套 var isYes = answer === 1 ? true : false; "no-unreachable": 2,//不能有无法执行的代码 "no-unused-expressions": 2,//禁止无用的表达式 "no-unused-vars": [2, {"vars": "all", "args": "after-used"}],//不能有声明后未被使用的变量或参数 "no-use-before-define": 2,//未定义前不能使用 "no-useless-call": 2,//禁止不必要的call和apply "no-void": 2,//禁用void操作符 "no-var": 0,//禁用var,用let和const代替 "no-warning-comments": [1, { "terms": ["todo", "fixme", "xxx"], "location": "start" }],//不能有警告备注 "no-with": 2,//禁用with "array-bracket-spacing": [2, "never"],//是否允许非空数组里面有多余的空格 "arrow-parens": 0,//箭头函数用小括号括起来 "arrow-spacing": 0,//=>的前/后括号 "accessor-pairs": 0,//在对象中使用getter/setter "block-scoped-var": 0,//块语句中使用var "brace-style": [1, "1tbs"],//大括号风格 "callback-return": 1,//避免多次调用回调什么的 "camelcase": 2,//强制驼峰法命名 "comma-dangle": [2, "never"],//对象字面量项尾不能有逗号 "comma-spacing": 0,//逗号前后的空格 "comma-style": [2, "last"],//逗号风格,换行时在行首还是行尾 "complexity": [0, 11],//循环复杂度 "computed-property-spacing": [0, "never"],//是否允许计算后的键名什么的 "consistent-return": 0,//return 后面是否允许省略 "consistent-this": [2, "that"],//this别名 "constructor-super": 0,//非派生类不能调用super,派生类必须调用super "curly": [2, "all"],//必须使用 if(){} 中的{} "default-case": 2,//switch语句最后必须有default "dot-location": 0,//对象访问符的位置,换行的时候在行首还是行尾 "dot-notation": [0, { "allowKeywords": true }],//避免不必要的方括号 "eol-last": 0,//文件以单一的换行符结束 "eqeqeq": 2,//必须使用全等 "func-names": 0,//函数表达式必须有名字 "func-style": [0, "declaration"],//函数风格,规定只能使用函数声明/函数表达式 "generator-star-spacing": 0,//生成器函数*的前后空格 "guard-for-in": 0,//for in循环要用if语句过滤 "handle-callback-err": 0,//nodejs 处理错误 "id-length": 0,//变量名长度 "indent": [2, 4],//缩进风格 "init-declarations": 0,//声明时必须赋初值 "key-spacing": [0, { "beforeColon": false, "afterColon": true }],//对象字面量中冒号的前后空格 "lines-around-comment": 0,//行前/行后备注 "max-depth": [0, 4],//嵌套块深度 "max-len": [0, 80, 4],//字符串最大长度 "max-nested-callbacks": [0, 2],//回调嵌套深度 "max-params": [0, 3],//函数最多只能有3个参数 "max-statements": [0, 10],//函数内最多有几个声明 "new-cap": 2,//函数名首行大写必须使用new方式调用,首行小写必须用不带new方式调用 "new-parens": 2,//new时必须加小括号 "newline-after-var": 2,//变量声明后是否需要空一行 "object-curly-spacing": [0, "never"],//大括号内是否允许不必要的空格 "object-shorthand": 0,//强制对象字面量缩写语法 "one-var": 1,//连续声明 "operator-assignment": [0, "always"],//赋值运算符 += -=什么的 "operator-linebreak": [2, "after"],//换行时运算符在行尾还是行首 "padded-blocks": 0,//块语句内行首行尾是否要空行 "prefer-const": 0,//首选const "prefer-spread": 0,//首选展开运算 "prefer-reflect": 0,//首选Reflect的方法 "quotes": [1, "single"],//引号类型 `` "" '' "quote-props":[2, "always"],//对象字面量中的属性名是否强制双引号 "radix": 2,//parseInt必须指定第二个参数 "id-match": 0,//命名检测 "require-yield": 0,//生成器函数必须有yield "semi": [2, "always"],//语句强制分号结尾 "semi-spacing": [0, {"before": false, "after": true}],//分号前后空格 "sort-vars": 0,//变量声明时排序 "space-after-keywords": [0, "always"],//关键字后面是否要空一格 "space-before-blocks": [0, "always"],//不以新行开始的块{前面要不要有空格 "space-before-function-paren": [0, "always"],//函数定义时括号前面要不要有空格 "space-in-parens": [0, "never"],//小括号里面要不要有空格 "space-infix-ops": 0,//中缀操作符周围要不要有空格 "space-return-throw-case": 2,//return throw case后面要不要加空格 "space-unary-ops": [0, { "words": true, "nonwords": false }],//一元运算符的前/后要不要加空格 "spaced-comment": 0,//注释风格要不要有空格什么的 "strict": 2,//使用严格模式 "use-isnan": 2,//禁止比较时使用NaN,只能用isNaN() "valid-jsdoc": 0,//jsdoc规则 "valid-typeof": 2,//必须使用合法的typeof的值 "vars-on-top": 2,//var必须放在作用域顶部 "wrap-iife": [2, "inside"],//立即执行函数表达式的小括号风格 "wrap-regex": 0,//正则表达式字面量用小括号包起来 "yoda": [2, "never"]//禁止尤达条件
规则解释二:
{ /** * 禁止 for 循环出现方向错误的循环,比如 for (i = 0; i < 10; i--) * @category Possible Errors */ 'for-direction': 'error', /** * getter 必须有返回值,并且禁止返回空,比如 return; * @category Possible Errors */ 'getter-return': [ 'error', { allowImplicit: false } ], /** * 禁止将 async 函数做为 new Promise 的回调函数 * @category Possible Errors * @reason 出现这种情况时,一般不需要使用 new Promise 实现异步了 */ 'no-async-promise-executor': 'error', /** * 禁止将 await 写在循环里,因为这样就无法同时发送多个异步请求了 * @category Possible Errors * @reason 要求太严格了,有时需要在循环中写 await */ 'no-await-in-loop': 'off', /** * 禁止与负零进行比较 * @category Possible Errors */ 'no-compare-neg-zero': 'error', /** * 禁止在判断表达式中使用赋值语句,除非这个赋值语句被括号包起来了 * @category Possible Errors */ 'no-cond-assign': ['error', 'except-parens'], /** * 禁止使用 console * @category Possible Errors * @reason console 的使用很常见 */ 'no-console': 'off', /** * 禁止将常量作为分支条件判断中的判断表达式,但允许作为循环条件判断中的测试表达式 * @category Possible Errors */ 'no-constant-condition': [ 'error', { checkLoops: false } ], /** * 禁止在正则表达式中出现 Ctrl 键的 ASCII 表示,即禁止使用 /\x1f/ * @category Possible Errors * @reason 几乎不会遇到这种场景 */ 'no-control-regex': 'error', /** * 禁止使用 debugger * @category Possible Errors */ 'no-debugger': 'error', /** * 禁止在函数参数中出现重复名称的参数 * @category Possible Errors */ 'no-dupe-args': 'error', /** * 禁止在对象字面量中出现重复名称的键名 * @category Possible Errors */ 'no-dupe-keys': 'error', /** * 禁止在 switch 语句中出现重复测试表达式的 case * @category Possible Errors */ 'no-duplicate-case': 'error', /** * 禁止出现空代码块,允许 catch 为空代码块 * @category Possible Errors */ 'no-empty': [ 'error', { allowEmptyCatch: true } ], /** * 禁止在正则表达式中使用空的字符集 [] * @category Possible Errors */ 'no-empty-character-class': 'error', /** * 禁止将 catch 的第一个参数 error 重新赋值 * @category Possible Errors */ 'no-ex-assign': 'error', /** * 禁止不必要的布尔类型转换,比如 !! 或 Boolean * @category Possible Errors * @fixable */ 'no-extra-boolean-cast': 'error', /** * 禁止函数表达式中出现多余的括号 * @category Possible Errors * @fixable */ 'no-extra-parens': ['error', 'functions'], /** * 禁止出现多余的分号 * @category Possible Errors * @fixable */ 'no-extra-semi': 'error', /** * 禁止将一个函数声明重新赋值,如: * @category Possible Errors */ 'no-func-assign': 'error', /** * 禁止在 if 代码块内出现函数声明 * @category Possible Errors */ 'no-inner-declarations': ['error', 'both'], /** * 禁止在 RegExp 构造函数中出现非法的正则表达式 * @category Possible Errors */ 'no-invalid-regexp': 'error', /** * 禁止使用特殊空白符(比如全角空格),除非是出现在字符串、正则表达式或模版字符串中 * @category Possible Errors */ 'no-irregular-whitespace': [ 'error', { skipStrings: true, skipComments: false, skipRegExps: true, skipTemplates: true } ], /** * 禁止正则表达式中使用肉眼无法区分的特殊字符 * @category Possible Errors * @reason 某些特殊字符很难看出差异,最好不要在正则中使用 */ 'no-misleading-character-class': 'error', /** * 禁止将 Math, JSON 或 Reflect 直接作为函数调用 * @category Possible Errors */ 'no-obj-calls': 'error', /** * 禁止使用 hasOwnProperty, isPrototypeOf 或 propertyIsEnumerable * @category Possible Errors * @reason hasOwnProperty 比较常用 */ 'no-prototype-builtins': 'off', /** * 禁止在正则表达式中出现连续的空格,必须使用 /foo {3}bar/ 代替 * @category Possible Errors * @fixable */ 'no-regex-spaces': 'error', /** * 禁止在数组中出现连续的逗号,如 let foo = [,,] * @category Possible Errors */ 'no-sparse-arrays': 'error', /** * 禁止在普通字符串中出现模版字符串里的变量形式,如 'Hello ${name}!' * @category Possible Errors */ 'no-template-curly-in-string': 'error', /** * 禁止出现难以理解的多行表达式 * @category Possible Errors */ 'no-unexpected-multiline': 'error', /** * 禁止在 return, throw, break 或 continue 之后还有代码 * @category Possible Errors */ 'no-unreachable': 'error', /** * 禁止在 finally 中出现 return, throw, break 或 continue * @category Possible Errors */ 'no-unsafe-finally': 'error', /** * 禁止在 in 或 instanceof 操作符的左侧使用感叹号,如 if (!key in object) * @category Possible Errors * @fixable */ 'no-unsafe-negation': 'error', /** * 禁止将 await 或 yield 的结果做为运算符的后面项 * @category Possible Errors * @reason 这样会导致不符合预期的结果 */ 'require-atomic-updates': 'error', /** * 必须使用 isNaN(foo) 而不是 foo === NaN * @category Possible Errors */ 'use-isnan': 'error', /** * typeof 表达式比较的对象必须是 'undefined', 'object', 'boolean', 'number', 'string', 'function' 或 'symbol' * @category Possible Errors */ 'valid-typeof': 'error', //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ /** * setter 必须有对应的 getter,getter 可以没有对应的 setter * @category Best Practices */ 'accessor-pairs': [ 'error', { setWithoutGet: true, getWithoutSet: false } ], /** * 数组的方法除了 forEach 之外,回调函数必须有返回值 * @category Best Practices */ 'array-callback-return': 'off', /** * 将 var 定义的变量视为块作用域,禁止在块外使用 * @category Best Practices */ 'block-scoped-var': 'error', /** * 在类的非静态方法中,必须存在对 this 的引用 * @category Best Practices * @reason 太严格了 */ 'class-methods-use-this': 'error', /** * 禁止函数的循环复杂度超过 20,https://en.wikipedia.org/wiki/Cyclomatic_complexity * @category Best Practices */ complexity: [ 'error', { max: 20 } ], /** * 禁止函数在不同分支返回不同类型的值 * @category Best Practices * @reason 太严格了 */ 'consistent-return': 'off', /** * if 后面必须要有 {,除非是单行 if * @category Best Practices * @fixable */ curly: ['error', 'multi-line', 'consistent'], /** * switch 语句必须有 default * @category Best Practices * @reason 太严格了 */ 'default-case': 'off', /** * 链式调用的时候,点号必须放在第二行开头处,禁止放在第一行结尾处 * @category Best Practices * @fixable */ 'dot-location': ['error', 'property'], /** * 禁止出现 foo['bar'],必须写成 foo.bar * @category Best Practices * @reason 当需要写一系列属性的时候,可以更统一 * @fixable */ 'dot-notation': 'off', /** * 必须使用 === 或 !==,禁止使用 == 或 !=,与 null 比较时除外 * @category Best Practices * @fixable */ eqeqeq: [ 'error', 'always', { null: 'ignore' } ], /** * for in 内部必须有 hasOwnProperty * @category Best Practices */ 'guard-for-in': 'error', /** * 限制一个文件中类的数量 * @category Best Practices */ 'max-classes-per-file': 'off', /** * 禁止使用 alert * @category Best Practices * @reason alert 很常用 */ 'no-alert': 'off', /** * 禁止使用 caller 或 callee * @category Best Practices */ 'no-caller': 'error', /** * switch 的 case 内有变量定义的时候,必须使用大括号将 case 内变成一个代码块 * @category Best Practices */ 'no-case-declarations': 'error', /** * 禁止在正则表达式中出现形似除法操作符的开头,如 let a = /=foo/ * @category Best Practices * @reason 有代码高亮的话,在阅读这种代码时,也完全不会产生歧义或理解上的困难 */ 'no-div-regex': 'off', /** * 禁止在 else 内使用 return,必须改为提前结束 * @category Best Practices * @reason else 中使用 return 可以使代码结构更清晰 * @fixable */ 'no-else-return': 'off', /** * 不允许有空函数,除非是将一个空函数设置为某个项的默认值 * @category Best Practices */ 'no-empty-function': [ 'error', { allow: ['functions', 'arrowFunctions'] } ], /** * 禁止解构中出现空 {} 或 [] * @category Best Practices */ 'no-empty-pattern': 'error', /** * 禁止使用 foo == null,必须使用 foo === null * @category Best Practices * @reason foo == null 比较常用,可以用于判断 foo 不是 undefined 并且不是 null,故允许此写法 */ 'no-eq-null': 'off', /** * 禁止使用 eval * @category Best Practices */ 'no-eval': 'error', /** * 禁止修改原生对象 * @category Best Practices */ 'no-extend-native': 'error', /** * 禁止出现没必要的 bind * @category Best Practices * @fixable */ 'no-extra-bind': 'error', /** * 禁止出现没必要的 label * @category Best Practices * @fixable */ 'no-extra-label': 'error', /** * switch 的 case 内必须有 break, return 或 throw * @category Best Practices */ 'no-fallthrough': 'error', /** * 表示小数时,禁止省略 0,比如 .5 * @category Best Practices * @fixable */ 'no-floating-decimal': 'error', /** * 禁止对全局变量赋值 * @category Best Practices */ 'no-global-assign': 'error', /** * 禁止使用 !! ~ 等难以理解的运算符,仅允许使用 !! * @category Best Practices * @fixable */ 'no-implicit-coercion': [ 'error', { allow: ['!!'] } ], /** * 禁止在全局作用域下定义变量或申明函数 * @category Best Practices */ 'no-implicit-globals': 'error', /** * 禁止在 setTimeout 或 setInterval 中传入字符串,如 setTimeout('alert("Hi!")', 100); * @category Best Practices */ 'no-implied-eval': 'error', /** * 禁止在类之外的地方使用 this * @category Best Practices * @reason this 的使用很灵活,事件回调中可以表示当前元素,函数也可以先用 this,等以后被调用的时候再 call */ 'no-invalid-this': 'off', /** * 禁止使用 __iterator__ * @category Best Practices */ 'no-iterator': 'error', /** * 禁止使用 label * @category Best Practices */ 'no-labels': 'error', /** * 禁止使用没必要的 {} 作为代码块 * @category Best Practices */ 'no-lone-blocks': 'error', /** * 禁止在循环内的函数中出现循环体条件语句中定义的变量 * @category Best Practices */ 'no-loop-func': 'error', /** * 禁止使用 magic numbers * @category Best Practices */ 'no-magic-numbers': 'off', /** * 禁止出现连续的多个空格,除非是注释前,或对齐对象的属性、变量定义、import 等 * @category Best Practices * @fixable */ 'no-multi-spaces': [ 'error', { ignoreEOLComments: true, exceptions: { Property: true, BinaryExpression: false, VariableDeclarator: true, ImportDeclaration: true } } ], /** * 禁止使用 \ 来换行字符串,应使用\n * @category Best Practices */ 'no-multi-str': 'error', /** * 禁止直接 new 一个类而不赋值 * @category Best Practices */ 'no-new': 'error', /** * 禁止使用 new Function,比如 let x = new Function("a", "b", "return a + b"); * @category Best Practices */ 'no-new-func': 'error', /** * 禁止使用 new 来生成 String, Number 或 Boolean * @category Best Practices */ 'no-new-wrappers': 'error', /** * 禁止使用 0 开头的数字表示八进制数 * @category Best Practices */ 'no-octal': 'error', /** * 禁止使用八进制的转义符 * @category Best Practices */ 'no-octal-escape': 'error', /** * 禁止对函数的参数重新赋值 * @category Best Practices */ 'no-param-reassign': 'off', /** * 禁止使用 __proto__ * @category Best Practices */ 'no-proto': 'error', /** * 禁止重复定义变量 * @category Best Practices */ 'no-redeclare': 'error', /** * 禁止使用指定的对象属性 * @category Best Practices * @reason 它用于限制某个具体的 api 不能使用 */ 'no-restricted-properties': 'off', /** * 禁止在 return 语句里赋值 * @category Best Practices */ 'no-return-assign': ['error', 'always'], /** * 禁止在 return 语句里使用 await * @category Best Practices */ 'no-return-await': 'error', /** * 禁止出现 location.href = 'javascript:void(0)'; * @category Best Practices */ 'no-script-url': 'error', /** * 禁止将自己赋值给自己 * @category Best Practices */ 'no-self-assign': 'error', /** * 禁止将自己与自己比较 * @category Best Practices */ 'no-self-compare': 'error', /** * 禁止使用逗号操作符 * @category Best Practices */ 'no-sequences': 'error', /** * 禁止 throw 字面量,必须 throw 一个 Error 对象 * @category Best Practices */ 'no-throw-literal': 'error', /** * 循环内必须对循环条件的变量有修改 * @category Best Practices */ 'no-unmodified-loop-condition': 'error', /** * 禁止无用的表达式 * @category Best Practices */ 'no-unused-expressions': [ 'error', { allowShortCircuit: true, allowTernary: true, allowTaggedTemplates: true } ], /** * 禁止出现没用的 label * @category Best Practices * @fixable */ 'no-unused-labels': 'error', /** * 禁止出现没必要的 call 或 apply * @category Best Practices */ 'no-useless-call': 'error', /** * 禁止在 catch 中仅仅只是把错误 throw 出去 * @category Best Practices * @reason 这样的 catch 是没有意义的,等价于直接执行 try 里的代码 */ 'no-useless-catch': 'error', /** * 禁止出现没必要的字符串连接 * @category Best Practices */ 'no-useless-concat': 'error', /** * 禁止出现没必要的转义 * @category Best Practices * @reason 转义可以使代码更易懂 */ 'no-useless-escape': 'off', /** * 禁止没必要的 return * @category Best Practices * @reason 没必要限制 return * @fixable */ 'no-useless-return': 'off', /** * 禁止使用 void * @category Best Practices */ 'no-void': 'error', /** * 禁止注释中出现 TODO 和 FIXME * @category Best Practices * @reason TODO 很常用 */ 'no-warning-comments': 'off', /** * 禁止使用 with * @category Best Practices */ 'no-with': 'error', /** * 使用 ES2018 中的正则表达式命名组 * @category Best Practices * @reason 正则表达式已经较难理解了,没必要强制加上命名组 */ 'prefer-named-capture-group': 'off', /** * Promise 的 reject 中必须传入 Error 对象,而不是字面量 * @category Best Practices */ 'prefer-promise-reject-errors': 'error', /** * parseInt 必须传入第二个参数 * @category Best Practices */ radix: 'error', /** * async 函数中必须存在 await 语句 * @category Best Practices * @reason async function 中没有 await 的写法很常见,比如 koa 的示例中就有这种用法 */ 'require-await': 'off', /** * 正则表达式中必须要加上 u 标志 * @category Best Practices */ 'require-unicode-regexp': 'off', /** * var 必须在作用域的最前面 * @category Best Practices * @reason var 不在最前面也是很常见的用法 */ 'vars-on-top': 'off', /** * 立即执行的函数必须符合如下格式 (function () { alert('Hello') })() * @category Best Practices * @fixable */ 'wrap-iife': [ 'error', 'inside', { functionPrototypeMethods: true } ], /** * 必须使用 if (foo === 5) 而不是 if (5 === foo) * @category Best Practices * @fixable */ yoda: [ 'error', 'never', { onlyEquality: true } ], /** * 禁止使用 'strict'; * @category Strict Mode * @fixable */ strict: ['error', 'never'], /** * 变量必须在定义的时候赋值 * @category Variables * @reason 先定义后赋值很常见 */ 'init-declarations': 'off', /** * 禁止使用 delete * @category Variables */ 'no-delete-var': 'error', /** * 禁止 label 名称与定义过的变量重复 * @category Variables */ 'no-label-var': 'error', /** * 禁止使用指定的全局变量 * @category Variables * @reason 它用于限制某个具体的变量名不能使用 */ 'no-restricted-globals': 'off', /** * 禁止变量名与上层作用域内的定义过的变量重复 * @category Variables * @reason 很多时候函数的形参和传参是同名的 */ 'no-shadow': 'off', /** * 禁止使用保留字作为变量名 * @category Variables */ 'no-shadow-restricted-names': 'error', /** * 禁止使用未定义的变量 * @category Variables */ 'no-undef': [ 'error', { typeof: false } ], /** * 禁止将 undefined 赋值给变量 * @category Variables * @fixable */ 'no-undef-init': 'error', /** * 禁止使用 undefined * @category Variables */ 'no-undefined': 'off', /** * 定义过的变量必须使用 * @category Variables */ 'no-unused-vars': [ 'error', { vars: 'all', args: 'none', caughtErrors: 'none', ignoreRestSiblings: true } ], /** * 变量必须先定义后使用 * @category Variables */ 'no-use-before-define': [ 'error', { functions: false, classes: false, variables: false } ], /** * callback 之后必须立即 return * @category Node.js and CommonJS * @reason Limitations 太多了 */ 'callback-return': 'off', /** * require 必须在全局作用域下 * @category Node.js and CommonJS * @reason 条件加载很常见 */ 'global-require': 'off', /** * callback 中的 error 必须被处理 * @category Node.js and CommonJS */ 'handle-callback-err': 'error', /** * 禁止直接使用 Buffer * @category Node.js and CommonJS */ 'no-buffer-constructor': 'error', /** * 相同类型的 require 必须放在一起 * @category Node.js and CommonJS * @reason 太严格了 */ 'no-mixed-requires': 'off', /** * 禁止直接 new require('foo') * @category Node.js and CommonJS */ 'no-new-require': 'error', /** * 禁止对 __dirname 或 __filename 使用字符串连接 * @category Node.js and CommonJS */ 'no-path-concat': 'error', /** * 禁止使用 process.env.NODE_ENV * @category Node.js and CommonJS * @reason 使用很常见 */ 'no-process-env': 'off', /** * 禁止使用 process.exit(0) * @category Node.js and CommonJS * @reason 使用很常见 */ 'no-process-exit': 'off', /** * 禁止使用指定的模块 * @category Node.js and CommonJS * @reason 它用于限制某个具体的模块不能使用 */ 'no-restricted-modules': 'off', /** * 禁止使用 node 中的同步的方法,比如 fs.readFileSync * @category Node.js and CommonJS * @reason 使用很常见 */ 'no-sync': 'off', /** * 配置数组的中括号内前后的换行格式 * @category Stylistic Issues * @reason 配置项无法配制成想要的样子 * @fixable */ 'array-bracket-newline': 'off', /** * 数组的括号内的前后禁止有空格 * @category Stylistic Issues * @fixable */ 'array-bracket-spacing': ['error', 'never'], /** * 配置数组的元素之间的换行格式 * @category Stylistic Issues * @reason 允许一行包含多个元素,方便大数量的数组的书写 * @fixable */ 'array-element-newline': 'off', /** * 代码块如果在一行内,那么大括号内的首尾必须有空格 * @category Stylistic Issues * @fixable */ 'block-spacing': ['error', 'always'], /** * if 与 else 的大括号风格必须一致 * @category Stylistic Issues * @reason else 代码块可能前面需要有一行注释 * @fixable */ 'brace-style': [ 'error', '1tbs', { 'allowSingleLine': true }], /** * 变量名必须是 camelcase 风格的 * @category Stylistic Issues * @reason 很多 api 或文件名都不是 camelcase */ camelcase: 'off', /** * 注释的首字母必须大写 * @category Stylistic Issues * @reason 没必要限制 * @fixable */ 'capitalized-comments': 'off', /** * 对象的最后一个属性末尾必须有逗号 * @category Stylistic Issues * @fixable */ 'comma-dangle': 'off', /** * 逗号前禁止有空格,逗号后必须要有空格 * @category Stylistic Issues * @fixable */ 'comma-spacing': [ 'error', { before: false, after: true } ], /** * 禁止在行首写逗号 * @category Stylistic Issues * @fixable */ 'comma-style': ['error', 'last'], /** * 用作对象的计算属性时,中括号内的首尾禁止有空格 * @category Stylistic Issues * @fixable */ 'computed-property-spacing': ['error', 'never'], /** * 限制 this 的别名 * @category Stylistic Issues * @reason 没必要限制 */ 'consistent-this': 'off', /** * 文件最后一行必须有一个空行 * @category Stylistic Issues * @reason 没必要限制 * @fixable */ 'eol-last': 'error', /** * 函数名和执行它的括号之间禁止有空格 * @category Stylistic Issues * @fixable */ 'func-call-spacing': ['error', 'never'], /** * 函数赋值给变量的时候,函数名必须与变量名一致 * @category Stylistic Issues */ 'func-name-matching': [ 'error', 'always', { includeCommonJSModuleExports: false } ], /** * 函数必须有名字 * @category Stylistic Issues * @reason 没必要限制 */ 'func-names': 'off', /** * 必须只使用函数声明或只使用函数表达式 * @category Stylistic Issues * @reason 没必要限制 */ 'func-style': 'off', /** * 函数参数要么同在一行要么每行一个 * @category Stylistic Issues * @fixable */ 'function-paren-newline': ['error', 'multiline'], /** * 禁止使用指定的标识符 * @category Stylistic Issues * @reason 它用于限制某个具体的标识符不能使用 */ 'id-blacklist': 'off', /** * 限制变量名长度 * @category Stylistic Issues * @reason 没必要限制变量名长度 */ 'id-length': 'off', /** * 限制变量名必须匹配指定的正则表达式 * @category Stylistic Issues * @reason 没必要限制变量名 */ 'id-match': 'off', /** * 箭头函数的函数体必须与箭头在同一行,或者被括号包裹 * @category Stylistic Issues * @autofix */ 'implicit-arrow-linebreak': ['error', 'beside'], /** * 一个缩进必须用四个空格替代 * @category Stylistic Issues * @fixable */ indent: [ 'error', 2, { SwitchCase: 1, flatTernaryExpressions: true } ], /** * jsx 中的属性必须用双引号 * @category Stylistic Issues * @fixable */ 'jsx-quotes': ['error', 'prefer-double'], /** * 对象字面量中冒号前面禁止有空格,后面必须有空格 * @category Stylistic Issues * @fixable */ 'key-spacing': [ 'error', { beforeColon: false, afterColon: true, mode: 'strict' } ], /** * 关键字前后必须有空格 * @category Stylistic Issues * @fixable */ 'keyword-spacing': [ 'error', { before: true, after: true } ], /** * 单行注释必须写在上一行 * @category Stylistic Issues * @reason 没必要限制 */ 'line-comment-position': 'off', /** * 限制换行符为 LF 或 CRLF * @category Stylistic Issues * @reason 没必要限制 * @fixable */ 'linebreak-style': 'off', /** * 注释前后必须有空行 * @category Stylistic Issues * @reason 没必要限制 * @fixable */ 'lines-around-comment': 'off', /** * 类的成员之间是否需要空行 * @category Stylistic Issues * @reason 有时为了紧凑需要挨在一起,有时为了可读性需要空一行 * @fixable */ 'lines-between-class-members': 'off', /** * 代码块嵌套的深度禁止超过 5 层 * @category Stylistic Issues */ 'max-depth': ['error', 5], /** * 限制一行的长度 * @category Stylistic Issues * @reason 现在编辑器已经很智能了,不需要限制一行的长度 */ 'max-len': 'off', /** * 限制一个文件最多的行数 * @category Stylistic Issues * @reason 没必要限制 */ 'max-lines': 'off', /** * 限制函数块中的代码行数 * @category Stylistic Issues */ 'max-lines-per-function': 'off', /** * 回调函数嵌套禁止超过 3 层,多了请用 async await 替代 * @category Stylistic Issues */ 'max-nested-callbacks': ['error', 3], /** * 函数的参数禁止超过 7 个 * @category Stylistic Issues */ 'max-params': ['error', 7], /** * 限制函数块中的语句数量 * @category Stylistic Issues * @reason 没必要限制 */ 'max-statements': 'off', /** * 限制一行中的语句数量 * @category Stylistic Issues * @reason 没必要限制 */ 'max-statements-per-line': 'off', /** * 约束多行注释的格式 * @category Stylistic Issues * @reason 能写注释已经不容易了,不需要限制太多 * @fixable */ 'multiline-comment-style': 'off', /** * 三元表达式必须得换行 * @category Stylistic Issues * @reason 三元表达式可以随意使用 */ 'multiline-ternary': 'off', /** * new 后面的类名必须首字母大写 * @category Stylistic Issues */ 'new-cap': [ 'error', { newIsCap: true, capIsNew: false, properties: true } ], /** * new 后面的类必须有小括号 * @category Stylistic Issues * @fixable */ 'new-parens': 'error', /** * 链式调用必须换行 * @category Stylistic Issues * @reason 没必要限制 */ 'newline-per-chained-call': 'off', /** * 禁止使用 Array 构造函数 * @category Stylistic Issues */ 'no-array-constructor': 'error', /** * 禁止使用位运算 * @category Stylistic Issues * @reason 位运算很常见 */ 'no-bitwise': 'off', /** * 禁止使用 continue * @category Stylistic Issues * @reason continue 很常用 */ 'no-continue': 'off', /** * 禁止在代码后添加内联注释 * @category Stylistic Issues * @reason 内联注释很常用 */ 'no-inline-comments': 'off', /** * 禁止 else 中只有一个单独的 if * @category Stylistic Issues * @reason 单独的 if 可以把逻辑表达的更清楚 * @fixable */ 'no-lonely-if': 'off', /** * 禁止混用不同的操作符,比如 let foo = a && b < 0 || c > 0 || d + 1 === 0 * @category Stylistic Issues * @reason 太严格了,可以由使用者自己去判断如何混用操作符 */ 'no-mixed-operators': 'off', /** * 禁止混用空格和缩进 * @category Stylistic Issues */ 'no-mixed-spaces-and-tabs': 'error', /** * 禁止连续赋值,比如 a = b = c = 5 * @category Stylistic Issues * @reason 没必要限制 */ 'no-multi-assign': 'off', /** * 禁止出现超过三行的连续空行 * @category Stylistic Issues * @fixable */ 'no-multiple-empty-lines': [ 'error', { max: 3, maxEOF: 1, maxBOF: 1 } ], /** * 禁止 if 里面有否定的表达式 * @category Stylistic Issues * @reason 否定的表达式可以把逻辑表达的更清楚 */ 'no-negated-condition': 'off', /** * 禁止使用嵌套的三元表达式,比如 a ? b : c ? d : e * @category Stylistic Issues * @reason 没必要限制 */ 'no-nested-ternary': 'off', /** * 禁止直接 new Object * @category Stylistic Issues */ 'no-new-object': 'error', /** * 禁止使用 ++ 或 -- * @category Stylistic Issues * @reason 没必要限制 */ 'no-plusplus': 'off', /** * 禁止使用特定的语法 * @category Stylistic Issues * @reason 它用于限制某个具体的语法不能使用 */ 'no-restricted-syntax': 'off', /** * 禁止使用 tabs * @category Stylistic Issues */ 'no-tabs': 'error', /** * 禁止使用三元表达式 * @category Stylistic Issues * @reason 三元表达式很常用 */ 'no-ternary': 'off', /** * 禁止行尾有空格 * @category Stylistic Issues * @fixable */ 'no-trailing-spaces': 'error', /** * 禁止变量名出现下划线 * @category Stylistic Issues * @reason 下划线在变量名中很常用 */ 'no-underscore-dangle': 'off', /** * 必须使用 !a 替代 a ? false : true * @category Stylistic Issues * @reason 后者表达的更清晰 * @fixable */ 'no-unneeded-ternary': 'error', /** * 禁止属性前有空格,比如 foo. bar() * @category Stylistic Issues * @fixable */ 'no-whitespace-before-property': 'error', /** * 禁止 if 后面不加大括号而写两行代码 * @category Stylistic Issues * @fixable */ 'nonblock-statement-body-position': [ 'error', 'beside', { overrides: { while: 'below' } } ], /** * 大括号内的首尾必须有换行 * @category Stylistic Issues * @fixable */ 'object-curly-newline': [ 'error', { multiline: true, consistent: true } ], /** * 对象字面量只有一行时,大括号内的首尾必须有空格 * @category Stylistic Issues * @fixable */ 'object-curly-spacing': [ 'error', 'always', { arraysInObjects: true, objectsInObjects: false } ], /** * 对象字面量内的属性每行必须只有一个 * @category Stylistic Issues * @reason 没必要限制 * @fixable */ 'object-property-newline': 'off', /** * 禁止变量申明时用逗号一次申明多个 * @category Stylistic Issues */ 'one-var': ['error', 'never'], /** * 变量申明必须每行一个 * @category Stylistic Issues * @fixable */ 'one-var-declaration-per-line': ['error', 'always'], /** * 必须使用 x = x + y 而不是 x += y * @category Stylistic Issues * @reason 没必要限制 * @fixable */ 'operator-assignment': 'off', /** * 需要换行的时候,操作符必须放在行末 * @category Stylistic Issues * @reason 有时放在第二行开始处更易读 * @fixable */ 'operator-linebreak': 'off', /** * 代码块首尾必须要空行 * @category Stylistic Issues * @reason 没必要限制 * @fixable */ 'padded-blocks': 'off', /** * 限制语句之间的空行规则,比如变量定义完之后必须要空行 * @category Stylistic Issues * @reason 没必要限制 * @fixable */ 'padding-line-between-statements': 'off', /** * 使用 ... 而不是 Object.assign * @category Stylistic Issues * @fixable */ 'prefer-object-spread': 'error', /** * 对象字面量的键名禁止用引号括起来 * @category Stylistic Issues * @reason 没必要限制 * @fixable */ 'quote-props': 'off', /** * 必须使用单引号,禁止使用双引号 * @category Stylistic Issues * @fixable */ quotes: [ 'error', 'single', { avoidEscape: true, allowTemplateLiterals: true } ], /** * 结尾必须没有分号 * @category Stylistic Issues * @fixable */ semi: ['error', 'never'], /** * 一行有多个语句时,分号前面禁止有空格,分号后面必须有空格 * @category Stylistic Issues * @fixable */ 'semi-spacing': [ 'error', { before: false, after: true } ], /** * 分号必须写在行尾,禁止在行首出现 * @category Stylistic Issues * @fixable */ 'semi-style': ['error', 'last'], /** * 对象字面量的键名必须排好序 * @category Stylistic Issues * @reason 没必要限制 */ 'sort-keys': 'off', /** * 变量申明必须排好序 * @category Stylistic Issues * @reason 没必要限制 * @autofix */ 'sort-vars': 'off', /** * if, function 等的大括号之前必须要有空格,比如 if (a) { * @category Stylistic Issues * @fixable */ 'space-before-blocks': ['error', 'always'], /** * 命名函数表达式括号前禁止有空格,箭头函数表达式括号前面必须有一个空格 * @category Stylistic Issues * @fixable */ 'space-before-function-paren': [ 'error', { anonymous: 'ignore', named: 'never', asyncArrow: 'always' } ], /** * 小括号内的首尾禁止有空格 * @category Stylistic Issues * @fixable */ 'space-in-parens': ['error', 'never'], /** * 操作符左右必须有空格 * @category Stylistic Issues * @fixable */ 'space-infix-ops': 'error', /** * new, typeof 等后面必须有空格,++, -- 等禁止有空格 * @category Stylistic Issues * @fixable */ 'space-unary-ops': [ 'error', { words: true, nonwords: false } ], /** * 注释的斜线或 * 后必须有空格 * @category Stylistic Issues * @fixable */ 'spaced-comment': [ 'error', 'always', { block: { exceptions: ['*'], balanced: true } } ], /** * case 的冒号前禁止有空格,冒号后必须有空格 * @category Stylistic Issues * @fixable */ 'switch-colon-spacing': [ 'error', { after: false, before: false } ], /** * 模版字符串的 tag 之后禁止有空格,比如 tag`Hello World` * @category Stylistic Issues * @fixable */ 'template-tag-spacing': ['error', 'never'], /** * 文件开头禁止有 BOM * @category Stylistic Issues * @fixable */ 'unicode-bom': ['error', 'never'], /** * 正则表达式必须有括号包起来 * @category Stylistic Issues * @reason 没必要限制 * @fixable */ 'wrap-regex': 'off', /** * 箭头函数能够省略 return 的时候,必须省略,比如必须写成 () => 0,禁止写成 () => { return 0 } * @category ECMAScript 6 * @reason 箭头函数的返回值,应该允许灵活设置 * @fixable */ 'arrow-body-style': 'off', /** * 箭头函数只有一个参数的时候,必须加括号 * @category ECMAScript 6 * @reason 应该允许灵活设置 * @fixable */ 'arrow-parens': 'off', /** * 箭头函数的箭头前后必须有空格 * @category ECMAScript 6 * @fixable */ 'arrow-spacing': [ 'error', { before: true, after: true } ], /** * constructor 中必须有 super * @category ECMAScript 6 */ 'constructor-super': 'error', /** * generator 的 * 前面禁止有空格,后面必须有空格 * @category ECMAScript 6 * @fixable */ 'generator-star-spacing': [ 'error', { before: false, after: true } ], /** * 禁止对定义过的 class 重新赋值 * @category ECMAScript 6 */ 'no-class-assign': 'error', /** * 禁止出现难以理解的箭头函数,比如 let x = a => 1 ? 2 : 3 * @category ECMAScript 6 * @fixable */ 'no-confusing-arrow': [ 'error', { allowParens: true } ], /** * 禁止对使用 const 定义的常量重新赋值 * @category ECMAScript 6 */ 'no-const-assign': 'error', /** * 禁止重复定义类 * @category ECMAScript 6 */ 'no-dupe-class-members': 'error', /** * 禁止重复 import 模块 * @category ECMAScript 6 */ 'no-duplicate-imports': 'error', /** * 禁止使用 new 来生成 Symbol * @category ECMAScript 6 */ 'no-new-symbol': 'error', /** * 禁止 import 指定的模块 * @category ECMAScript 6 * @reason 它用于限制某个具体的模块不能使用 */ 'no-restricted-imports': 'off', /** * 禁止在 super 被调用之前使用 this 或 super * @category ECMAScript 6 */ 'no-this-before-super': 'error', /** * 禁止出现没必要的计算键名,比如 let a = { ['0']: 0 }; * @category ECMAScript 6 * @fixable */ 'no-useless-computed-key': 'error', /** * 禁止出现没必要的 constructor,比如 constructor(value) { super(value) } * @category ECMAScript 6 */ 'no-useless-constructor': 'error', /** * 禁止解构时出现同样名字的的重命名,比如 let { foo: foo } = bar; * @category ECMAScript 6 * @fixable */ 'no-useless-rename': 'error', /** * 禁止使用 var * @category ECMAScript 6 * @fixable */ 'no-var': 'error', /** * 必须使用 a = {b} 而不是 a = {b: b} * @category ECMAScript 6 * @reason 没必要强制要求 * @fixable */ 'object-shorthand': 'off', /** * 必须使用箭头函数作为回调 * @category ECMAScript 6 * @reason 没必要强制要求 * @fixable */ 'prefer-arrow-callback': 'off', /** * 申明后不再被修改的变量必须使用 const 来申明 * @category ECMAScript 6 * @reason 没必要强制要求 * @fixable */ 'prefer-const': 'error', /** * 必须使用解构 * @category ECMAScript 6 * @reason 没必要强制要求 */ 'prefer-destructuring': 'off', /** * 必须使用 0b11111011 而不是 parseInt('111110111', 2) * @category ECMAScript 6 * @reason 没必要强制要求 * @fixable */ 'prefer-numeric-literals': 'off', /** * 必须使用 ...args 而不是 arguments * @category ECMAScript 6 * @reason 没必要强制要求 */ 'prefer-rest-params': 'off', /** * 必须使用 ... 而不是 apply,比如 foo(...args) * @category ECMAScript 6 * @reason apply 很常用 * @fixable */ 'prefer-spread': 'off', /** * 必须使用模版字符串而不是字符串连接 * @category ECMAScript 6 * @reason 字符串连接很常用 * @fixable */ 'prefer-template': 'off', /** * generator 函数内必须有 yield * @category ECMAScript 6 */ 'require-yield': 'error', /** * ... 的后面禁止有空格 * @category ECMAScript 6 * @fixable */ 'rest-spread-spacing': ['error', 'never'], /** * import 必须按规则排序 * @category ECMAScript 6 * @reason 没必要强制要求 * @fixable */ 'sort-imports': 'off', /** * 创建 Symbol 时必须传入参数 * @category ECMAScript 6 */ 'symbol-description': 'error', /** * ${name} 内的首尾禁止有空格 * @category ECMAScript 6 * @fixable */ 'template-curly-spacing': ['error', 'never'], /** * yield* 后面必须要有空格 * @category ECMAScript 6 * @fixable */ 'yield-star-spacing': ['error', 'after'] }
2.4、改正错误的方式
有三种方法来修正错误:
- 手动修正: 手动修改
- 命令修正:npm run lint
- 插件修正: 配合vscode 中的eslint插件
2.4.1、命令修正
src/index.js
if(!!(typeof window!=="undefined")){ console.log("Hello window!"); }
执行命令:
执行命令:npx eslint index.js --fix
双重否定被删除。
使用 npm 脚本
我们添加一个 npm scripts 来运行 ESLint 规则。
例如,假设您的 package.json 文件包含以下行:
{ "scripts": { "lint:fix": "eslint . --fix" } }
现在,您只需要在命令行运行 npm run lint:fix,它将修复它可修复的内容。
"lint": "eslint --fix --ext .js,.vue src"
"lint":"eslint --fix --ext .js,.vue,.ts ."
2.4.2、插件修正
vscode中安装插件,安装插件后可以修正错误。
设置
// ESLint 插件的配置 "editor.codeActionsOnSave": { "source.fixAll": true, },
插件的使用
插件可以修正错误,可以忽视错误。
2.5、配置ESLint
如果在同一目录下存在多个配置文件,ESLint 将按照以下优先顺序以此使用其一:
.eslintrc.js
.eslintrc.cjs
.eslintrc.yaml
.eslintrc.yml
.eslintrc.json
package.json
2.5.1、环境配置
要在配置文件中使用 env
键指定环境,并通过将每个环境设置为 true
想启用的环境。例如,下面是启用浏览器和 Node.js 环境的例子:
{
"env": {
"browser": true,
"node": true
}
}
或者在 package.json
文件中
{
"name": "mypackage",
"version": "0.0.1",
"eslintConfig": {
"env": {
"browser": true,
"node": true
}
}
}
2.5.2、配置规则
ESLint 有大量的内置规则,你可以通过插件添加更多的规则。你也可以通过配置注释或配置文件来修改你的项目使用哪些规则。要改变一个规则的设置,你必须把规则的 ID 设置为这些值之一。
"off"
或0
- 关闭规则"warn"
或1
- 启用并视作警告(不影响退出)。"error"
或2
- 启用并视作错误(触发时退出代码为 1)
2.5.2.1、使用配置注释
eqeqeq:使用类型安全的相等运算符 ===
和 !==
而不是它们的常规运算符 ==
和 !=
被认为是好的做法。
curly:当一个块只包含一个语句时,JavaScript 允许省略大括号。然而,许多人认为,最好的做法是永远不要在块周围省略大括号,即使它们是可选的,因为这可能导致错误并降低代码的清晰度。
(1)、字符指定规则
要使用配置注释在文件中配置规则,请使用以下格式的注释:
/* eslint eqeqeq: "off", curly: "error" */
(2)、数字指定规则
在这个例子中,关闭 eqeqeq
,启用 curly
并视作错误。你也可以使用数字等价物来表示规则的严重程度。
/* eslint eqeqeq: 0, curly: 2 */
这个例子与上一个例子相同,只是它使用了数字代码而不是字符串值。关闭 eqeqeq
规则,curly
规则设置为错误。
(3)、指定额外选项
如果一个规则有额外的选项,你可以使用数组字面的语法来指定它们,比如:
/* eslint quotes: ["error", "double"], curly: 2 */
这个注释为 quotes
规则指定了“双重”选项。数组中的第一项总是规则的严重程度(数字或字符串)。
"double"
(默认值)要求尽可能使用双引号。"single"
要求尽可能使用单引号。"backtick"
要求尽可能使用反斜线。
(4)、配置注释
配置注释可以包括描述,以解释为什么注释是必要的。描述必须出现在配置之后,并以两个或多个连续的 -
字符与配置分开。比如。
/* eslint eqeqeq: "off", curly: "error" -- Here's a description about why this configuration is necessary. */
/* eslint eqeqeq: "off", curly: "error"
--------
Here's a description about why this configuration is necessary. */
/* eslint eqeqeq: "off", curly: "error"
* --------
* This will not work due to the line above starting with a '*' character.
*/
使用配置文件
要在配置文件中配置规则,请使用 rules
键和一个错误级别以及任何你想使用的选项。比如:
{
"rules": {
"eqeqeq": "off",
"curly": "error",
"quotes": ["error", "double"]
}
}
而在 YAML 中则是:
---
rules:
eqeqeq: off
curly: error
quotes:
- error
- double
要配置一个定义在插件中的规则,你必须在规则的 ID 前加上插件的名称和 /
。比如说:
{
"plugins": [
"plugin1"
],
"rules": {
"eqeqeq": "off",
"curly": "error",
"quotes": ["error", "double"],
"plugin1/rule1": "error"
}
}
而在 YAML 中则是:
---
plugins:
- plugin1
rules:
eqeqeq: 0
curly: error
quotes:
- error
- "double"
plugin1/rule1: error
在这些配置文件中,规则 plugin1/rule1
来自名为 plugin1
的插件。你也可以在配置注释中使用这种格式,比如:
/* eslint "plugin1/rule1": "error" */
注意:当从插件中指定规则时,确保省略 eslint-plugin-
。ESLint 只在内部使用无前缀的名字来定位规则。
2.5.3、禁用规则
使用配置注释
(1)、禁用所有规则
要在你的文件中暂时禁用规则警告,可以使用以下格式的块状注释:
/* eslint-disable */
alert('foo');
/* eslint-enable */
(2)、禁用特定规则
你还可以禁用或启用特定规则的警告:
/* eslint-disable no-alert, no-console */
alert('foo');
console.log('bar');
/* eslint-enable no-alert, no-console */
注意:/* eslint-enable */
没有列出任何特定的规则将导致所有被禁用的规则被重新启用。
要禁用整个文件中的规则警告,在文件的顶部写入 /* eslint-disable */
块注释:
/* eslint-disable */
alert('foo');
你还可以在整个文件范围内禁用或启用特定规则:
/* eslint-disable no-alert */
alert('foo');
为了确保永远不会使用一个规则(无论未来是否会有任何启用/禁用行):
/* eslint no-alert: "off" */
alert('foo');
(3)、禁用特定行规则
要禁用某一特定行的所有规则,请使用以下格式之一的行或块注释:
alert('foo'); // eslint-disable-line
// eslint-disable-next-line
alert('foo');
/* eslint-disable-next-line */
alert('foo');
alert('foo'); /* eslint-disable-line */
(4)、要禁用某一特定行的特定规则:
alert('foo'); // eslint-disable-line no-alert
// eslint-disable-next-line no-alert
alert('foo');
alert('foo'); /* eslint-disable-line no-alert */
/* eslint-disable-next-line no-alert */
alert('foo');
(5)、要禁用一个特定行的多个规则:
alert('foo'); // eslint-disable-line no-alert, quotes, semi
// eslint-disable-next-line no-alert, quotes, semi
alert('foo');
alert('foo'); /* eslint-disable-line no-alert, quotes, semi */
/* eslint-disable-next-line no-alert, quotes, semi */
alert('foo');
/* eslint-disable-next-line
no-alert,
quotes,
semi
*/
alert('foo');
字符串选项:
"always"
(默认值)要求在语句的结尾处使用分号。"never"
不允许将分号作为语句的结尾(除非用于区分以[
,(
,/
,+
或-
开头的语句)。
对象选项("always"
时 ):
"omitLastInOneLineBlock": true
忽略一个块中的最后一个分号,因为它的大括号(以及该块的内容)都在同一行中。
对象选项("never"
时):
"beforeStatementContinuationChars": "any"
(默认值)[
,(
,/
,+
或-
开头,则忽略语句末尾的分号(或缺少分号)。"beforeStatementContinuationChars": "always"
如果下一行以[
,(
,/
,+
或-
开头,则要求在语句的末尾加上分号。"beforeStatementContinuationChars": "never"
不允许将分号作为语句的结尾,如果它不会造成 ASI 危险,即使下一行以[
,(
,/
,+
或-
开头。
注意:beforeStatementContinuationChars
不适用于类域,因为类域不是语句。
上述所有方法也适用于插件规则。比如,要禁用 eslint-plugin-example
的 rule-name
规则,将插件的名称(example
)和规则的名称(rule-name
)合并为 example/rule-name
:
foo(); // eslint-disable-line example/rule-name
foo(); /* eslint-disable-line example/rule-name */
配置注释可以包括说明,以解释为什么注释是必要的。描述必须在配置之后,并且需要用两个或多个连续的 -
字符与配置分开。比如:
// eslint-disable-next-line no-console -- Here's a description about why this configuration is necessary.
console.log('hello');
/* eslint-disable-next-line no-console --
* Here's a very long description about why this configuration is necessary
* along with some additional information
**/
console.log('hello');
注意:禁用文件一部分的警告的注释告诉 ESLint 不要报告被禁用的代码违反规则。然而,ESLint 仍然解析整个文件,所以禁用的代码仍然需要是语法上有效的 JavaScript。
使用配置文件
要在配置文件中禁用一组文件的规则,请使用 overrides
键和 files
键。比如:
{
"rules": {...},
"overrides": [
{
"files": ["*-test.js","*.spec.js"],
"rules": {
"no-unused-expressions": "off"
}
}
]
}
no-unused-expressions:一个未使用的表达式对程序的状态没有影响,表明是一个逻辑错误。
例如,n + 1;
不是一个语法错误,但它可能是一个打字错误,程序员的意思是一个赋值语句 n += 1;
。有时,这种未使用的表达式可能会被生产环境中的一些构建工具消除,这可能会破坏应用逻辑。
禁用内联注释
要禁用所有内联配置注释,请使用 noInlineConfig
设置。比如:
{
"rules": {...},
"noInlineConfig": true
}
这个设置类似于 –no-inline-config CLI 选项。
2.5.4、配置文件中的 ignorePatterns
你可以在你的配置文件中使用 ignorePatterns
来告诉 ESLint 忽略特定的文件和目录。ignorePatterns
模式遵循与 .eslintignore
相同的规则。参见.eslintignore
文档了解更多内容。
{
"ignorePatterns": ["temp.js", "**/vendor/*.js"],
"rules": {
//...
}
}
ignorePatterns
中的 glob 模式是相对于配置文件所在的目录而言的。- 你不能在
overrides
属性中使用ignorePatterns
属性。 - 在
.eslintignore
中定义的模式优先于配置文件的ignorePatterns
属性。
如果 glob 模式以 /
开头,该模式是相对于配置文件的基本目录而言的。例如,lib/.eslintrc.json
中的 /foo.js
会匹配 lib/foo.js
,而不是匹配lib/subdir/foo.js
。
如果配置是通过 --config
CLI 选项提供的,配置中以 /
开头的忽略模式是相对于当前工作目录的,而不是给定配置的基本目录。例如,如果使用 --config configs/.eslintrc.json
,配置中的忽略模式是基于 .
而不是 ./configs
。
2.5.5.eslintignore
文件
你可以通过在项目的根目录下创建 .eslintignore
文件来告诉 ESLint 要忽略哪些文件和目录。.eslintignore
文件是一个纯文本文件,其中每一行都是一个 glob 模式,表示哪些路径应该被省略掉。例如,下面的内容将忽略所有的 JavaScript 文件:
**/*.js
当运行 ESLint 时,在决定要检查的文件范围前,它会在当前工作目录中寻找 .eslintignore
文件。如果找到该文件,那么在遍历目录时就会应用这些偏好。每次只能使用一个 .eslintignore
文件,且仅会使用当前工作目录中的 .eslintignore
文件。
Glob 使用 node-ignore 进行匹配,因此有许多特性:
- 以
#
开头的行被视为注释,不影响忽略模式。 - 路径是相对于当前工作目录的。这也适用于通过
--ignore-pattern
命令传递的路径。 - 前面有
!
的行是否定模式,重新包括被先前模式忽略的模式。 - 忽略模式的行为与
.gitignore
规范一致。
特别要注意的是,像 .gitignore
文件一样,所有用作 .eslintignore
和 --ignore-pattern
的模式的路径必须使用正斜杠作为路径分隔符。
# Valid
/root/src/*.js
# Invalid
\root\src\*.js
请参阅 .gitignore
的规范,了解更多有效的语法实例。
除了 .eslintignore
文件中的任何模式外,ESLint 总是遵循一些隐含的忽略规则,即使通过了 --no-ignore
标志。这些隐含的规则如下:
- 忽略
node_modules/
- 忽略点文件(除了
.eslintrc.*
),以及点文件夹和它们的内容
这些规则也有一些例外:
-
如果要检查的路径是一个 glob 模式或目录路径,并且是点文件夹,则检查所有点文件和点文件夹,包括目录结构深处的点文件和点文件夹。
例如,
eslint .config/
将对.config
目录下的所有点文件夹和点文件进行检查,包括一级子目录以及在目录结构中更深的子目录。 -
如果要检查的路径是一个特定的文件路径,并且通过了
--no-ignore
标志,ESLint 将检查该文件,而不考虑隐含的忽略规则。例如,
eslint .config/my-config-file.js --no-ignore
将检查my-config-file.js
。需要注意的是,同样的命令如果没有--no-ignore
行,就不会对my-config-file.js
文件进行检测。 -
通过
--ignore-pattern
或.eslintignore
指定的 Allowlist 和 denylist 规则会优先于隐含的忽略规则。例如,在这种情况下,
.build/test.js
是允许列表的理想文件。因为默认忽略了所有点文件夹及其子文件,.build
必须首先要处于允许列表中,这样 eslint 才会知道它的子文件。然后,.build/test.js
必须被明确地列入允许列表,而其余的内容则被拒绝列表。这可以通过以下.eslintignore
文件完成:# Allowlist 'test.js' in the '.build' folder # But do not allow anything else in the '.build' folder to be linted !.build .build/* !.build/test.js
与下面的
--ignore-pattern
一样:eslint --ignore-pattern '!.build' --ignore-pattern '.build/*' --ig
2.5.6、配置插件
ESLint 支持使用第三方插件。在使用插件之前,你必须使用 npm 安装它。
要在配置文件内配置插件,请使用 plugins
键,它应该是由插件名称组成的列表。可以省略插件名称中的 eslint-plugin-
前缀。
{
"plugins": [
"plugin1",
"eslint-plugin-plugin2"
]
}
安装插件:eslint-plugin-html检查html中的语法
配置文件:
plugins: ["html"],
2.6、在vite与vue3中使用eslint
2.6.1、创建一个vite项目
npm create vite@latest
package.json配置
上图为控制台输入npm run dev后,展示的内容,为了获取本地IP,可以在配置的时候加上--host,方便自动获取本地网络地址;由于Vite的快是因为它将代码分为依赖和源码,依赖大多数时间不会改变,所以在开发运行中,依赖只会请求一次,而如果我们更新了依赖,浏览器没有同步更新就可能会造成运行错误,所以可以在脚本内添加–force来避免错误,每次启动运行脚本就会更新依赖,避免浏览器的强缓存所带来的影响,具体内容可以去Vite官网查看学习,这里不再展开。下图是脚本的配置:
将原来的"dev": "vite" 🔀 "dev": "vite --force --host"进行替换,这样就可以输出网络访问地址,每次运行也会更新依赖内容。
2.6.2、集成eslint
1.安装ESLint
npm add -D eslint
2.初始化ESLint配置
npx eslint --init
3.安装vite-plugin-eslint(eslint结合vite使用)
// 说明: 该包是用于配置vite运行的时候自动检测eslint规范 不符合页面会报错
npm add -D vite-plugin-eslint
4.配置vite.config.ts文件
import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; import eslintPlugin from 'vite-plugin-eslint'; // https://vitejs.dev/config/ export default defineConfig({ plugins: [ vue(), eslintPlugin({ include: ['src/**/*.ts', 'src/**/*.vue', 'src/*.ts', 'src/*.vue'], }), ], resolve: { // 配置路径别名 alias: { '@': '/src', }, }, });
2.6.3、指定解析器
如果这时候就到这里结束了,则会出现:Parsing error: '>' expected.eslint的错误,
默认情况下,ESLint 使用Espree 作为其解析器。 [...] 要指定 npm 模块用作解析器,请使用 .eslintrc
文件中的 parser
选项指定它。
安装vue-eslint-parser
npm i -D vue-eslint-parser
修改配置文件
parser: 'vue-eslint-parser', parserOptions: { ecmaVersion: 2020, sourceType: 'moudule', parser: '@typescript-eslint/parser', },
'@typescript-eslint/no-explicit-any': 'off', // 允许ts使用any
3、emoji绘文字
emoji(绘文字)是一种图形字符,网络中经常用作表情符号。emoji不是图片,每个emoji都像文字一样拥有独立编码并且可以存放于字库中,所以可以理解其为图形文字,实际使用中也是和文字一样的使用,可以复制粘贴和输入。
emoji流行于网络中,较新的电脑和手机系统基本都支持显示emoji符号,它们大多拥有独立的emoji图形字库文件,可能包含的数量有所不同。
编码方面,国标码GB18030和国际码Unicode中都有收录emoji图形符号。在Unicode编码中,emoji主要安排在1号平面第241行至第247行(1F000-1F6FF),以及0号平面第39行和40行(2600-27FF)等位置。
以下将显示1184个emoji图形文字,想要看到更大字号的emoji,请前往上方Unicode编码中提到的链接,打开页面后鼠标划到emoji字符上方(触摸屏则点击)可看到该字符放大后的效果以及其Unicode编码。emoji图形文字和普通文字一样可复制粘贴,如果输入法有emoji输入功能也可直接输入。可以通过设置字号改变emoji图形大小,但可能无法设置其颜色,因部分emoji的颜色被固化在系统中,例如道路禁止车辆驶入emoji⛔。
©️®️‼️⁉️™️ℹ️↔️↕️↖️↗️↘️↙️↩️↪️⌚⌛⌨️⏏️⏩⏪⏫⏬⏭️⏮️⏯️⏰⏱️⏲️⏳⏸️⏹️⏺️Ⓜ️▪️▫️▶️◀️◻️◼️◽◾☀️☁️☂️☃️☄️☎️☑️☔☕☘️☝️☠️☢️☣️☦️☪️☮️☯️☸️☹️☺️♀️♂️♈♉♊♋♌♍♎♏♐♑♒♓♠️♣️♥️♦️♨️♻️♿⚒️⚓⚔️⚕️⚖️⚗️⚙️⚛️⚜️⚠️⚡⚪⚫⚰️⚱️⚽⚾⛄⛅⛈️⛎⛏️⛑️⛓️⛔⛩️⛪⛰️⛱️⛲⛳⛴️⛵⛷️⛸️⛹️⛺⛽✂️✅✈️✉️✊✋✌️✍️✏️✒️✔️✖️✝️✡️✨✳️✴️❄️❇️❌❎❓❔❕❗❣️❤️➕➖➗➡️➰➿⤴️⤵️⬅️⬆️⬇️⬛⬜⭐⭕〰️〽️㊗️㊙️🀄🃏🅰️🅱️🅾️🅿️🆎🆑🆒🆓🆔🆕🆖🆗🆘🆙🆚🈁🈂️🈚🈯🈲🈳🈴🈵🈶🈷️🈸🈹🈺🉐🉑🌀🌁🌂🌃🌄🌅🌆🌇🌈🌉🌊🌋🌌🌍🌎🌏🌐🌑🌒🌓🌔🌕🌖🌗🌘🌙🌚🌛🌜🌝🌞🌟🌠🌡️🌤️🌥️🌦️🌧️🌨️🌩️🌪️🌫️🌬️🌭🌮🌯🌰🌱🌲🌳🌴🌵🌶️🌷🌸🌹🌺🌻🌼🌽🌾🌿🍀🍁🍂🍃🍄🍅🍆🍇🍈🍉🍊🍋🍌🍍🍎🍏🍐🍑🍒🍓🍔🍕🍖🍗🍘🍙🍚🍛🍜🍝🍞🍟🍠🍡🍢🍣🍤🍥🍦🍧🍨🍩🍪🍫🍬🍭🍮🍯🍰🍱🍲🍳🍴🍵🍶🍷🍸🍹🍺🍻🍼🍽️🎀🎁🎂🎃🎄🎅🎆🎇🎈🎉🎊🎋🎌🎍🎎🎏🎐🎑🎒🎓🎖️🎗️🎙️🎚️🎛️🎞️🎟️🎠🎡🎢🎣🎤🎥🎦🎧🎨🎩🎪🎫🎬🎭🎮🎯🎰🎱🎲🎳🎴🎵🎶🎷🎸🎹🎺🎻🎼🎽🎾🎿🏀🏁🏂🏃🏄🏅🏆🏇🏈🏉🏊🏋️🏌️🏍️🏎️🏔️🏕️🏖️🏗️🏘️🏙️🏚️🏛️🏜️🏝️🏞️🏟️🏠🏡🏢🏣🏤🏥🏦🏧🏨🏩🏪🏫🏬🏭🏮🏯🏰🏳️🏴🏵️🏷️🐀🐁🐂🐃🐄🐅🐆🐇🐈🐉🐊🐋🐌🐍🐎🐏🐐🐑🐒🐓🐔🐕🐖🐗🐘🐙🐚🐛🐜🐝🐞🐟🐠🐡🐢🐣🐤🐥🐦🐧🐨🐩🐪🐫🐬🐭🐮🐯🐰🐱🐲🐳🐴🐵🐶🐷🐸🐹🐺🐻🐼🐽🐾🐿️👀👁️👂👃👄👅👆👇👈👉👊👋👌👍👎👏👐👑👒👓👔👕👖👗👘👙👚👛👜👝👞👟👠👡👢👣👤👥👦👧👨👩👪👫👬👭👮👯👰👱👲👳👴👵👶👷👸👹👺👻👼👽👾👿💀💁💂💃💄💅💆💇💈💉💊💋💌💍💎💏💐💑💒💓💔💕💖💗💘💙💚💛💜💝💞💟💠💡💢💣💤💥💦💧💨💩💪💫💬💭💮💯💰💱💲💳💴💵💶💷💸💹💺💻💼💽💾💿📀📁📂📃📄📅📆📇📈📉📊📋📌📍📎📏📐📑📒📓📔📕📖📗📘📙📚📛📜📝📞📟📠📡📢📣📤📥📦📧📨📩📪📫📬📭📮📯📰📱📲📳📴📵📶📷📸📹📺📻📼📽️📿🔀🔁🔂🔃🔄🔅🔆🔇🔈🔉🔊🔋🔌🔍🔎🔏🔐🔑🔒🔓🔔🔕🔖🔗🔘🔙🔚🔛🔜🔝🔞🔟🔠🔡🔢🔣🔤🔥🔦🔧🔨🔩🔪🔫🔬🔭🔮🔯🔰🔱🔲🔳🔴🔵🔶🔷🔸🔹🔺🔻🔼🔽🕉️🕊️🕐🕑🕒🕓🕔🕕🕖🕗🕘🕙🕚🕛🕜🕝🕞🕟🕠🕡🕢🕣🕤🕥🕦🕧🕯️🕰️🕳️🕴️🕵️🕶️🕷️🕸️🕹️🖇️🖊️🖋️🖌️🖍️🖐️🖕🖖🖤🖥️🖨️🖱️🖲️🖼️🗂️🗃️🗄️🗑️🗒️🗓️🗜️🗝️🗞️🗡️🗣️🗨️🗯️🗳️🗺️🗻🗼🗽🗾🗿😀😁😂😃😄😅😆😇😈😉😊😋😌😍😎😏😐😑😒😓😔😕😖😗😘😙😚😛😜😝😞😟😠😡😢😣😤😥😦😧😨😩😪😫😬😭😮😯😰😱😲😳😴😵😶😷😸😹😺😻😼😽😾😿🙀🙁🙂🙅🙆🙇🙈🙉🙊🙋🙌🙍🙎🙏🚀🚁🚂🚃🚄🚅🚆🚇🚈🚉🚊🚋🚌🚍🚎🚏🚐🚑🚒🚓🚔🚕🚖🚗🚘🚙🚚🚛🚜🚝🚞🚟🚠🚡🚢🚣🚤🚥🚦🚧🚨🚩🚪🚫🚬🚭🚮🚯🚰🚱🚲🚳🚴🚵🚶🚷🚸🚹🚺🚻🚼🚽🚾🚿🛀🛁🛂🛃🛄🛅🛋️🛌🛍️🛎️🛏️🛠️🛡️🛢️🛣️🛤️🛥️🛩️🛫🛬🛰️🛳️
emoji在Unicode编码中的位置:
2010年10月发布的Unicode 6.0版首次收录绘文字编码,其中582个绘文字符号,66个已在其他位置编码,保留作兼容用途的绘文字符号。在Unicode 9.0 用22区块中共计1,126个字符表示绘文字,其中1,085个是独立绘文字字符,26个是用来显示旗帜的区域指示符号以及 12 个(#, * and 0-9)键帽符号。
杂项符号及图形768个字符中有637是绘文字;增补符号及图形82个字符中有80个是绘文字;所有80个表情符号都是绘文字;交通及地图符号103个字符中有92个是绘文字;杂项符号256个字符中有80个是绘文字;装饰符号192个字符中有33个是绘文字。
四、作业
1、完成一个猜成语的APP,打包,发布,上架