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

能夠看出整個項目的配置項是至關的少, 不少都黑盒處理了, 讓前端能夠更關注業務, 以後我會進一步研究其源碼, 敬請期待.

附上整個項目地址

相關文章
相關標籤/搜索