vite 与 react 的结合

vite, 法语词, 快的意思. 读音为 /vit/css

先来看看以前的先驱: parcel, rollup, webpack.这些工具的目的即是为了打包, 为了前端能有模块化. 为了前端能承担更复杂的逻辑, 不被后端瞧不起.为了证实js是宇宙第一的语言, 为了.... 简单总结下:html

  1. 配置项
    • parcel最方便, 几乎不须要任何配置, install以后build便可.
    • webpack和rollup都须要指定entry, output,loaders, plugins, transformations等 -是rollup基于的是node的模块系统, 能够直接使用import/output, 这也是为何使用rollup须要在版本10以上的缘由. 并且webpack不能
    • webpack必须使用绝对路径, 这也是为何使用path.resolve的缘由 rollup可使用相对路径
  2. tree-shaking
    • parcel同时支持对commonjs以及es6的树摇. 这是很大的优点, 由于npm上还有不少是commonjs的库, 并且parcel在树摇时是平行摇的, 能够充分利用好多核的优点
    • rollup静态解析导入的代码, 自动排除未引入部分, 配置较少
    • webpack配置较为复杂, 必须使用es6的语法, webpack4在生产环境默认启用树摇了, 不然还须要配置uglifyPlugin插件
  3. 代码分段 code-split
    • webpack更优, 一整套配置, 能够较为精细化的控制, 参见官方示例
    • rollup使用浏览器内建的ES模块系统, 由浏览器来进行控制
    • parcel支持零配置的代码分段, 是经过动态导入语法import()来实现的, 该函数返回一个promise
    • 后二者issue和bug的报告比较多, 因此安全起见, webpack更为稳妥, 在compile的时候也是webpack最快.
  4. live reload 实时重载
    • 不用多说, 这是前端开发必备的功能 若是一个code的变化还须要我去按刷新的话, 估计个人command + R键会被按爆.
    • parcel自带有开发服务器, 可是在使用HTTP log hooks 和中间件的时候容易出问题
    • rollup须要安装rollup-plugin-serverrollup-plugin-livereload
    • webpack只须要安装webpack-dev-server便可, 就自定义性来讲(配置钩子, 中间件), webpack碾压其他两个
  5. HMR
    • 这也是开发不可少的, 特别是前端业务愈来愈重, 每次都要回首页从新点击简直痛苦(论首屏时间的重要性), 特别是在改css的时候(改一个字体大小你给我把整个页面都刷了??)
    • webpack简单配置一下, 在须要热更新的地方加上module.accept便可, 相比于其余二者, 更成熟, 自由度更好
    • parcel再一次内建了热更新机制
    • rollup须要rollup-plugin-hotreload插件
  6. 模块转换
    • 将非js格式转化为js格式(bundler只认js)
    • webpack就是一堆loader的配置
    • parcel再一次对常见的格式提供了内建的转换和转译, 无需配置和安装插件

总结来讲 若是是一个demo或者功能是可预期的简单(不是产品说的那种), 使用parcel 若是是最小化的第三方导入的一个库, 使用rollup 其他的使用webpack前端

说了一堆没用的vue

前端老是有更多更大的轮子被创造出来, 挺好, 百花齐放, 百家争鸣, 百舸争流, 百依百顺. 大佬老是很闲, 没法理解底层搬砖的辛苦, 尤大在vue3.0时着重提了一把, 既然轮子都到眼前了,仍是抡一抡.node

首先看看vite的描述 开发环境下使用原生esm,生产环境使用Rollup打包 的一个网页开发构建工具 很天然继承了两者的优势:react

  1. esm的优势webpack

    • 即时热模块替换(HMR)
  2. Rollup的优势git

    • 按需编译, 更多特性参照前文

esm是基于浏览器的实现的,固然该标准在ES6中已经提出,兼容性请参考 mdn, 这里仅仅简单的提几点:es6

  1. 原生模块的导出和引用

test.mjsgithub

export const test = () => {
    console.log('test')
}
复制代码

index.js

import { test } from "./test.mjs";
test()
复制代码

index.html

<script src="./index.js" type="module"></script>
复制代码

上述代码不须要通过任何的babel或webpack,直接能够被浏览器运行并打印test

  1. 能够导出函数,var,const,let,类
  2. mjsjs都可, 只是mdn官方推荐使用js先, 由于不少服务器的content-type不认识mjs, 会致使解析出错.因此沿用js便可
  3. 动态加载模块, 实现懒加载
btn.addEventListener('click', () => {
    import('./someDynamicModule').then(module => {
        // handleModule
    })
})
复制代码

与webpack的比较:

  1. Vite没有在开发阶段进行打包的操做, 源代码中的ES导入语法是直接从浏览器中实现的. 浏览器经过以前说的<script type="module">来实例化他们, 每个的导入都是一个HTTP请求.
  2. 开发环境须要作的事情就是拦截并进行代码转换浏览器没法解析的格式, 好比 '*.vue, *.jsx'等.至关于webpack的loader.可是仅仅只有loader的做用, 其余的并不涉及
  3. 生产环境Vite依然使用了bundle, 但用的是更轻量的rollup而不是webpack, 具体这二者的渊源请参见

这样的好处是什么呢?

  1. 不用打包, 因此冷启动很快
  2. 代码按需编译, 自然的树摇和懒加载
  3. HMR从依赖整个模块的数量中解耦出来因此不会由于app的增大而致使HMR的速度下降,

第三点我想着重说一下, webpack的HMR之因此须要设置module.accept就是但愿开发者能在真的须要热更新的地方使用, 由于一旦监听, 就会监听这个模块以及这个模块关联的全部依赖的变化, 这是比较消耗资源的, 并且一旦发现变化会将整个模块以及关联的模块都从新编译一次. 那么你说是否是很耗时间和性能?若是能够对每一个单独的模块进行监听和重编译, 是否是美滋滋?

不过也不是没有缺点

  1. 在整个网页从新加载的时候会比webpack慢, 由于是基于原生es, 须要在遍历到<script type="module">的时候发一次网络请求, 而且在那个模块中有可能还有其余的模块, 还得继续发网络请求.可是在首次以后就可使用缓存了, 也不是不能够接受, 并且也能够选择在开发环境时使用rollup进行打包.

下面来实战一下, 由于vue的独占期, 因此对vue的项目是无缝结合的, 可是我在工做中更多的是应用到了react, 如下代码为与react的结合

  1. 新建项目 yarn init -y
  2. 安装依赖yarn add @pika/react @pika/react-dom vite @pika是esm模块的前缀, 也就是react和react-dom的esm模块形式
  3. 添加react的支持配置 vite.config.js
module.exports = {
    jsx: 'react',
    plugins: [require('vite-plugin-react')]
}
复制代码
  1. 项目根目录建立index.html, 以下
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <link rel="icon" href="/favicon.ico" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Vite App</title>
</head>
<body>
  <div id="app"></div>
  <script type="module" src="/src/main.tsx"></script>
</body>
</html>
复制代码
  1. 新建src/main.tsx, 以下
import React from 'react'
import style from './index.module.scss'
export default function() {
    const [count, setCount] = React.useState(1)
    return (
        <div>
            hello world
            <button className={style.button} onClick={() => setCount(count + 1)}>
                count: {count}
            </button>
        </div>
    )
}
复制代码
  1. 关于css的模块化和预处理器 实际上vite建议使用原生的css变量, 由于他的目标是现代浏览器. 若是非要使用预处理器也能够, 有三种方案, 请参考这篇文章, 决定采用生成d.ts的方案, 由于这样能够有代码提示, 更香.因而选择安装typed-scss-modules以及sass, 加个"tsm": "tsm src -w"便可.这里要注意, 使用模块化的引入, 也就是import style from 'xxx.scss'须要遵循vue中的命名规范, 须要加一个module后缀, 也就是必须命名为xxx.module.scss

能够看出整个项目的配置项是至关的少, 不少都黑盒处理了, 让前端能够更关注业务, 以后我会进一步研究其源码, 敬请期待.

附上整个项目地址

相关文章
相关标签/搜索