Day3 vite的特点(上)

发布时间:2024年01月04日

根本上

从根本上来说,使用 Vite 进行开发与使用静态文件服务器没有太大区别。但是,Vite 相对于本机 ESM 导入提供了许多增强功能,以支持基于捆绑器的设置中常见的各种功能。

NPM 依赖关系解析和预捆绑

问题描述

  • 原生 ES 导入不支持裸模块(bare module)导入,如下所示:如下代码将在浏览器中引发错误

import { someMethod } from 'my-dep'

vite解决

  • Vite 将在所有提供的源文件中检测此类裸模块导入并执行以下操作:

    • (使用 esbuild 执行预捆绑)预捆绑它们以提高页面加载速度并将 CommonJS / UMD 模块转换为 ESM。

      • 这也是 Vite 的冷启动时间明显快于任何基于 JavaScript 的捆绑器的原因之一

  • 将导入重写为有效的 URL,例如 /node_modules/.vite/deps/my-dep.js?v=f3sf2ebd ,以便浏览器可以正确导入它们。

依赖项被强缓存

  • Vite 通过 HTTP 标头缓存依赖项请求,已解析的依赖项请求使用 HTTP 标头 max-age=31536000,immutable 进行强缓存,以提高开发期间的页面重新加载性能。

    • 一旦缓存,这些请求将永远不会再次到达开发服务器。

    • 如果安装了不同的版本(在包管理器锁定文件中有新的版本反映),缓存会因为新附加的不同版本请求而自动失效。

    • 如果您想通过进行本地编辑来调试依赖项,您可以:

      • 通过浏览器开发工具的“网络”选项卡暂时禁用缓存;

      • 使用 --force 标志重新启动 Vite 开发服务器以重新捆绑 deps;

      • 重新加载页面。

模块热更换

  • Vite 在原生 ESM 上提供 HMR API。

    • 具有 HMR 功能的框架可以利用 API 提供即时、精确的更新,而无需重新加载页面或破坏应用程序状态。

    • Vite 为 Vue 单文件组件和 React Fast Refresh 提供第一方 HMR 集成。

    • vite也提供通过 @prefresh/vite 的 Preact 官方集成。

注意

  • 当您通过 create-vite 创建应用程序时,您就不再需要手动设置热更新集成,,所选模板已经为您预先配置了

TypeScript

Vite 支持直接导入 .ts 文件。

仅转译

  • 什么是仅转译

    • Vite 仅对 .ts 文件执行转译,不执行类型检查。它假设类型检查由您的 IDE 和构建过程负责。

  • 为什么仅转译

    • Vite 不在转换过程中执行类型检查的原因是这两个作业的工作方式根本不同

      • 转译可以在每个文件的基础上工作,并与 Vite 的按需编译模型完美契合

      • 类型检查需要了解整个模块图,对 Vite 的转换管道进行类型检查将不可避免地损害 Vite 的速度优势。

  • 我们如何做仅转译

    • Vite 的工作就是将你的源模块转化为可以在浏览器中尽可能快地运行的形式。因此,建议:

      • 将静态分析检查(例如 ESLint)与 Vite 的转换管道分开

      • 对于生产构建,除了 Vite 的构建命令之外,您还可以运行 tsc --noEmit

      • 在开发过程中,如果您需要的不仅仅是 IDE 提示,我们建议在单独的进程中运行 tsc --noEmit --watch ,或者如果您希望直接在浏览器中报告类型错误,请使用 vite-plugin-checker。

        • tsc --noEmit --watch说明

          tsc --noEmit --watch 命令是 TypeScript 编译器 (TypeScript Compiler) 的命令行选项之一。这个命令的作用是启动 TypeScript 编译器并监视指定的文件,当文件发生变化时,自动进行增量编译。这意味着编译器会在后台持续监视文件的变化,并在检测到变化时自动重新编译文件,而不需要手动执行编译命令。

          --noEmit 选项告诉 TypeScript 编译器不生成任何输出文件,这意味着编译器只会检查代码并报告潜在的错误,而不会生成实际的 JavaScript 文件。

          --watch 选项则启用了监视模式,使得编译器能够持续监视指定的文件,并在文件发生变化时自动进行增量编译。

          这个命令通常用于开发过程中,以便在代码发生变化时自动进行编译,从而加快开发周期并帮助开发人员及时发现代码错误。

      • Vite转译

        • 使用 esbuild 将 TypeScript 转译为 JavaScript,速度比普通 tsc 快约 20~30 倍,并且 HMR 更新可以在 50 毫秒内反映在浏览器中。

  • 使用仅类型导入和导出语法可以避免潜在问题,例如错误捆绑仅类型导入,例如

import type { T } from 'only/types'
export type { T }

TypeScript 编译器选项

  • tsconfig.jsoncompilerOptions 下的一些配置字段需要特别注意。

isolatedModules应设置为 true

- 原因:
?
 ?  - `esbuild` 仅执行没有类型信息的转译,它不支持某些功能,例如 const enum 和隐式仅类型导入。
?
 ?  - 设置 `"isolatedModules": true` ,以便 TS 会针对不适用于隔离转译的功能发出警告。
?
- 注意
?
 ?  - 某些库(例如 `vue` )不能与 `"isolatedModules": true` 很好地配合。您可以使用 `"skipLibCheck": true` 暂时抑制错误,直到上游修复该错误。
useDefineForClassFields
  • 默认值

    • 从 Vite 2.5.0 开始,如果 TypeScript 目标是 ESNextES2022 或更新版本,则默认值为 true 。它与 tsc4.3.2 及更高版本的行为一致。这也是标准的 ECMAScript 运行时行为。

    • 其他 TypeScript 目标将默认为 false

  • 注意

    • 如果您使用的库严重依赖类字段,请注意该库的预期用途。

    • 大多数库都需要 "useDefineForClassFields": true ,例如 MobX。

    • 一些库尚未转换为这个新的默认值,包括 lit-element 。在这些情况下,请明确将 useDefineForClassFields 设置为 false

target

  • 默认情况

    • Vite 不会使用配置的 target 值转译 TypeScript,其行为与 esbuild 相同。

  • 如何设置转译目标

    可以使用 esbuild.target 选项来代替,默认为 esnext 以最小化转译。在构建中, build.target 选项具有更高的优先级,如果需要也可以设置。

useDefineForClassFields
  • 问题:

    • 如果 target 不是 ESNextES2022 或更新版本,或者没有 tsconfig.json 文件, useDefineForClassFields 将默认到 false

    • 这对于 esnext 的默认 esbuild.target 值可能会出现问题。它可能会转换为您的浏览器不支持的静态初始化块

  • 建议

    • target 设置为 ESNextES2022 或更高版本,

    • 或在配置 tsconfig.json 时明确显示将 useDefineForClassFields 设置为 true

影响构建结果的其他编译器选项?

  • [extends](https://www.typescriptlang.org/tsconfig#extends)

  • [importsNotUsedAsValues](https://www.typescriptlang.org/tsconfig#importsNotUsedAsValues)

  • [preserveValueImports](https://www.typescriptlang.org/tsconfig#preserveValueImports)

  • [verbatimModuleSyntax](https://www.typescriptlang.org/tsconfig#verbatimModuleSyntax)

  • [jsx](https://www.typescriptlang.org/tsconfig#jsx)

  • [jsxFactory](https://www.typescriptlang.org/tsconfig#jsxFactory)

  • [jsxFragmentFactory](https://www.typescriptlang.org/tsconfig#jsxFragmentFactory)

  • [jsxImportSource](https://www.typescriptlang.org/tsconfig#jsxImportSource)

  • [experimentalDecorators](https://www.typescriptlang.org/tsconfig#experimentalDecorators)

  • [alwaysStrict](https://www.typescriptlang.org/tsconfig#alwaysStrict)

其他

Vite 入门模板默认具有 "skipLibCheck": "true" 以避免类型检查依赖性,因为它们可能选择仅支持 TypeScript 的特定版本和配置。您可以在 vuejs/vue-cli#5688 了解更多信息。

Client Types 客户类型

填充客户端代码环境
  • Vite 的默认类型适用于其 Node.js API。要在 Vite 应用程序中填充客户端代码的环境,

    • 选择1:请添加 d.ts 声明文件:

/// <reference types="vite/client" />
  • 选择2:将 vite/client 添加到 tsconfig.json 内的 compilerOptions.types

{
  "compilerOptions": {
    "types": ["vite/client"]
  }
}
  • 这将提供以下类型的垫片:

    • Asset资产导入(例如导入 .svg 文件)

    • import.meta.envimport.meta.env 上 Vite 注入的环境变量的类型

    • import.meta.hotimport.meta.hot 上 HMR API 的类型

覆盖默认类型
  • 要覆盖默认vite/client类型

    • 请添加包含您的类型的类型定义文件

    • vite/client 之前添加类型引用。

  • 例如,要默认导入 *.svg 一个 React 组件:

  • vite-env-override.d.ts (包含您输入内容的文件):
  • declare module '*.svg' {
      const content: React.FC<React.SVGProps<SVGElement>>
      export default content
    }
    
  • 包含对 vite/client 引用的文件:
  • /// <reference types="./vite-env-override.d.ts" />
    /// <reference types="vite/client" />
    

Vue?

Vite 提供一流的 Vue 支持:

  • 通过 @vitejs/plugin-vue 支持 Vue 3 SFC

  • 通过 @vitejs/plugin-vue-jsx 支持 Vue 3 JSX

  • 通过 @vitejs/plugin-vue2 支持 Vue 2.7 SFC

  • 通过 @vitejs/plugin-vue2-jsx 支持 Vue 2.7 JSX

JSX?

  • 对jsx的支持情况

    • .jsx.tsx 文件也受到开箱即用的支持。 JSX 转译也是通过 esbuild 处理的。

  • 相关的jsx插件

    • Vue 用户应该使用官方的 @vitejs/plugin-vue-jsx 插件,

      • 它提供了 Vue 3 的特定功能,包括 HMR、全局组件解析、指令和槽。

  • react和vue之外的框架的使用

    • 如果不将 JSX 与 React 或 Vue 一起使用,则可以

      • 使用 esbuild 选项配置自定义 jsxFactoryjsxFragment 。以 Preact 为例:

        // vite.config.js
        import { defineConfig } from 'vite'
        
        export default defineConfig({
          esbuild: {
            jsxFactory: 'h',
            jsxFragment: 'Fragment',
          },
        })
        //更多详细信息,请参阅 esbuild 文档
        
  • 导入

    • 您可以使用 jsxInject (这是仅限 Vite 的选项)注入 JSX 帮助程序,以避免手动导入:

    // vite.config.js
    import { defineConfig } from 'vite'
    
    export default defineConfig({
      esbuild: {
        jsxInject: `import React from 'react'`,
      },
    })
    

CSS?

导入 .css 文件将通过支持 HMR 的 <style> 标记将其内容注入页面。

@import 内联和变基

  • ?@import内联

    • Vite 已预先配置为通过 postcss-import 支持 CSS @import 内联

    • Vite 别名也受到 CSS @import 的支持。

    • 所有 CSS url() 引用,即使导入的文件位于不同的目录中,也始终会自动重新设置基准以确保正确性。

  • 变基

    • Sass 和 Less 文件还支持 @import 别名和 URL 变基(请参阅 CSS 预处理器)。

PostCSS 后CSS?

  • postcss配置的应用范围

    • 如果项目包含有效的 PostCSS 配置(postcss-load-config 支持的任何格式,例如 postcss.config.js

      • 它将自动应用于所有导入的 CSS。

  • 运行postcss之后

    • CSS minification将在 PostCSS 之后运行,并将使用 build.cssTarget 选项。

CSS Modules CSS 模块

  • ?什么是css模块文件

    • 任何以 .module.css 结尾的 CSS 文件都被视为 CSS 模块文件。

  • 导入css模块文件之后会返回什么

    • 导入这样的文件将返回相应的模块对象:

  • 栗子

/* example.module.css */
.red {
  color: red;
}
import classes from './example.module.css'
document.getElementById('foo').className = classes.red
  • 配置CSS 模块行为

    • 可以通过 css.modules 选项进行配置。

    • 栗子

      • 如果 css.modules.localsConvention 设置为启用驼峰式本地命名(例如 localsConvention: 'camelCaseOnly' ),您还可以使用命名导入:

      // .apply-color -> applyColor
      import { applyColor } from './example.module.css'
      document.getElementById('foo').className = applyColor
      

CSS Pre-processors CSS 预处理器

  • ?怎么使用预处理器

    • 与postcss结合

      • 由于 Vite 仅针对现代浏览器,因此建议将原生 CSS 变量与实现 CSSWG 草案(例如 postcss-nesting)的 PostCSS 插件一起使用,并编写符合未来标准的普通 CSS。

    • 安装相应的预处理器

      • Vite 确实提供了对 .scss.sass.less.styl.stylus 文件的内置支持。不需要为它们安装 Vite 特定的插件,但必须安装相应的预处理器本身:
      • # .scss and .sass
        npm add -D sass
        
        # .less
        npm add -D less
        
        # .styl and .stylus
        npm add -D stylus
        

    • 与css模块结合

      • 在文件扩展名前添加 .module 来将 CSS 模块与预处理器结合使用,例如 style.module.scss

  • 使用预处理器之后

    • 如果使用 Vue 单文件组件,这也会自动启用 <style lang="sass"> 等。

    • Vite 改进了 Sass 和 Less 的 @import 解析,以便 Vite 别名也受到支持。

    • 此外,导入的 Sass/Less 文件中与根文件位于不同目录中的相对 url() 引用也会自动重新设置基准以确保正确性。

    • 由于 API 限制,Stylus .@import 不支持别名和 URL 变基。

Disabling CSS injection into the page 禁用 CSS 注入页面

  • ?如何禁用注入css

    • 可以通过 ?inline 查询参数关闭 CSS 内容的自动注入。

      • 在这种情况下,处理后的 CSS 字符串照常作为模块的默认导出返回,但样式不会注入到页面中。

      import './foo.css' // will be injected into the page
      import otherStyles from './bar.css?inline' // will not be injected
      
  • 注意

    • 自 Vite 5 起,CSS 文件中的默认导入和命名导入(例如 import style from './foo.css' )已被删除。请改用 ?inline 查询。

Lightning CSS 闪电 CSS

  • ?如何开启Lighting css

    • 从Vite 4.4开始,实验性支持Lightning CSS。

    • css.transformer: 'lightningcss' 添加到配置文件

    • 安装可选的 lightningcss 依赖项来选择加入
    • npm add -D lightningcss
      

  • 如何使用lighting css

    • 如果启用,CSS 文件将由 Lightning CSS 而不是 PostCSS 处理。

    • 使用 Lightning CSS 时不支持 CSS 预处理器。

    • 要配置它,您可以将 Lightning CSS 选项传递给 css.lightingcss 配置选项。

      • 要配置 CSS 模块,您将使用 css.lightningcss.cssModules 而不是 css.modules (它配置 PostCSS 处理 CSS 模块的方式)。

      • css缩小器

        • 默认情况下,Vite 使用 esbuild 来缩小 CSS。 Lightning CSS 还可以与 build.cssMinify: 'lightningcss' 一起用作 CSS 缩小器。

Static Assets 静态资源

导入静态资源将在提供服务时返回已解析的公共 URL

import imgUrl from './img.png'
document.getElementById('hero-img').src = imgUrl

特殊查询可以修改资产的加载方式:

// Explicitly load assets as URL//显式地将资产加载为URL
import assetAsURL from './asset.js?url'
// Load assets as strings//将资产加载为字符串
import assetAsString from './shader.glsl?raw'
// Load Web Workers//加载Web worker
import Worker from './worker.js?worker'
// Web Workers inlined as base64 strings at build time//Web worker在构建时内联为base64字符串
import InlineWorker from './worker.js?worker&inline

将资产导入为 URL

导入静态资源将在提供服务时返回已解析的公共 URL:

  • imgUrl 在开发期间将是 /img.png ,并在生产版本中变为 /assets/img.2d8efhg.png

    • 该行为类似于 webpack 的 file-loader 。不同之处在于导入可以使用绝对公共路径(基于开发期间的项目根)或相对路径。

import imgUrl from './img.png'
document.getElementById('hero-img').src = imgUrl

注意

  • CSS 中的 url() 引用的处理方式相同。

  • 如果使用 Vue 插件,Vue SFC 模板中的资源引用会自动转换为导入。

  • 常见图像、媒体和字体文件类型会自动检测为资产。您可以使用 assetsInclude 选项扩展内部列表。

  • 引用的资产作为构建资产图的一部分包含在内,将获得散列文件名,并且可以由插件处理以进行优化。

  • 小于 assetsInlineLimit 选项的字节数的资源将内联为 base64 数据 URL。

  • 默认情况下,TypeScript 不会将静态资源导入识别为有效模块。要解决此问题,请包含 vite/client

  • Git LFS 占位符会自动从内联中排除,因为它们不包含它们所代表的文件的内容。要进行内联,请确保在构建之前通过 Git LFS 下载文件内容。

Explicit URL Imports 显式 URL 导入

  • 适用场景

    • 未包含在内部列表或 assetsInclude 中的资源

      • 可以使用 ?url 后缀作为 URL 显式导入。

  • 例如

    • 这对于导入 Houdini Paint Worklets 很有用。

    import workletURL from 'extra-scalloped-border/worklet.js?url'
    CSS.paintWorklet.addModule(workletURL)
    

Importing Asset as String 将资产导入为字符串?

可以使用 ?raw 后缀将资源作为字符串导入。

import shaderString from './shader.glsl?raw'

Importing Script as a Worker 作为 Worker 导入脚本

脚本可以作为带有 ?worker?sharedworker 后缀的 Web Worker 导入。

// Separate chunk in the production build//在生产构建中分离块
import Worker from './shader.js?worker'
const worker = new Worker()
// sharedworker
import SharedWorker from './shader.js?sharedworker'
const sharedWorker = new SharedWorker()
// Inlined as base64 strings//内联为base64字符
import InlineWorker from './shader.js?worker&inline'

JSON

JSON 文件可以直接导入 - 还支持命名导入:

// import the entire object//导入整个对象
import json from './example.json'
// import a root field as named exports - helps with tree-shaking!//导入一个名为exports的根字段——有助于树摇!
import { field } from './example.json'
文章来源:https://blog.csdn.net/m0_73653709/article/details/135326832
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。