<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          為開發(fā)提速,項目 Webpack 轉(zhuǎn) Vite 實戰(zhàn)!(實用)

          共 9869字,需瀏覽 20分鐘

           ·

          2021-06-13 13:04

          Webpack to Vite

          背景

          最近,就 前端開發(fā)過程中的痛點及可優(yōu)化項 做了一次收集。 其中,構(gòu)建耗時、項目編譯速度慢 的字眼出現(xiàn)了好幾次。

          隨著業(yè)務的快速發(fā)展,我們很多項目的體積也快速膨脹。隨之而來的, 就是打包變慢等問題。

          提升研發(fā)效率,是技術人永恒的追求。

          我們項目也有啟動慢的問題,同事也提到過幾次。剛好我之前也做過類似的探索和優(yōu)化, 于是就借這個機會,改造一下項目, 解決啟動耗時的問題

          于昨天下午(2021.4.7 23:00), 成功嵌入 Vite, 項目啟動時間由約 190s => 20s, 熱更新時間縮短為 2s

          中間踩了一些坑, 好在最后爬出來了, 相關技術要點都會在下文中呈現(xiàn)。

          FBI Warning:以下文字,只是我結(jié)合自己的實際項目, 總結(jié)出來的一些淺薄的經(jīng)驗, 如有錯誤,歡迎指正 :)

          今天的主要內(nèi)容:

          • 為什么 Vite 啟動這么快
          • 我的項目如何植入 Vite
          • 改造過程中遇到的問題以及解決方式
          • 關于 Vite 開發(fā)、打包上線的一些思考
          • 相關代碼和結(jié)論

          正文

          為什么 Vite 啟動這么快

          底層實現(xiàn)上, Vite 是基于 esbuild 預構(gòu)建依賴的。

          esbuild 使用 go 編寫,并且比以 js 編寫的打包器預構(gòu)建依賴, 快 10 - 100 倍。

          因為 js 跟 go 相比實在是太慢了,js 的一般操作都是毫秒計,go 則是納秒。

          另外, 兩者的啟動方式也有所差異。

          webpack 啟動方式

          image.png

          Vite 啟動方式

          image.png

          Webpack 會先打包,然后啟動開發(fā)服務器,請求服務器時直接給予打包結(jié)果。

          而 Vite 是直接啟動開發(fā)服務器,請求哪個模塊再對該模塊進行實時編譯

          由于現(xiàn)代瀏覽器本身就支持 ES Module,會自動向依賴的 Module 發(fā)出請求。

          Vite 充分利用了這一點,將開發(fā)環(huán)境下的模塊文件,就作為瀏覽器要執(zhí)行的文件,而不是像 W ebpack 那樣進行打包合并

          由于 Vite 在啟動的時候不需要打包,也就意味著不需要分析模塊的依賴不需要編譯。因此啟動速度非常快。當瀏覽器請求某個模塊時,再根據(jù)需要對模塊內(nèi)容進行編譯。

          這種按需動態(tài)編譯的方式,極大的縮減了編譯時間,項目越復雜、模塊越多,vite 的優(yōu)勢越明顯。

          在 HMR(熱更新)方面,當改動了一個模塊后,僅需讓瀏覽器重新請求該模塊即可,不像webpack那樣需要把該模塊的相關依賴模塊全部編譯一次,效率更高。

          從實際的開發(fā)體驗來看, 在 Vite 模式下, 開發(fā)環(huán)境可以瞬間啟動, 但是等到頁面出來, 要等一段時間。

          我的項目如何植入 Vite

          新項目

          創(chuàng)建一個 Vite 新項目就比較簡單:

          yarn create @vitejs/app
          image.png
          image.png

          生成好之后, 直接啟動就可以了:

          image.png

          已有項目

          已有項目的遷移, 稍微繁瑣一些。

          首先, 加入 Vite 的相關配置。這里我使用了一個 cli 工具:wp2vite.

          安裝好之后, 直接執(zhí)行:

          image.png

          這一步, 會自動生成 Vite 的配置文件,并引入相關的依賴。

          把依賴安裝一下, 啟動就可以了。

          如果沒有意外的話, 你會收獲一堆報錯

          恭喜你,進入開心愉快的踩坑環(huán)節(jié)。

          我在改造過程中遇到的問題

          1. alias 錯誤

          image.png

          項目代碼里配置了一些別名,vite 無法識別,所以需要在vite 里面也配置 alias:

            resolve: {
              alias: {
                '@': resolve(__dirname, 'src'),
              },
            },

          2. 無法識別 less 全局變量

          image.png

          解決辦法:

          把自定義的全局變量從外部注入即可, 直接在 vite.config.js 的 css 選項中加入:

            css: {
              preprocessorOptions: {
                less: {
                  modifyVars: {
                    hack`true;@import '${resolve('./src/vars.less')}';`,
                    ...themeVariables,
                  },
                  javascriptEnabledtrue,
                },
              },
            },

          3. Uncaught Error: Target container is not a DOM element.

          image.png

          根元素未找到。

          原因是:默認生成的 index.html 中:

          <div id="root"></div>

          id 是 root, 而邏輯中的是#app, 這里直接改成 id=app 即可。

          4. typings 文件找不到

          image.png

          typings 文件未找到

          這個錯誤, 乍一看, 一頭霧水。

          進去看一下源代碼和編譯后的代碼:

          源代碼:

          image.png

          編譯后:

          image.png
          image.png

          typings 文件這不是好好的在這嗎, 怎么就找不到?

          想了一下:Vite 不知道 typeings 文件是不需要被編譯的,需要告訴編譯器不編譯這個文件。

          最后在 TS 官方文檔里找到了答案:

          https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html

          Type-Only Imports and Export

          This feature is something most users may never have to think about; however, if you’ve hit issues under --isolatedModules, TypeScript’s transpileModule API, or Babel, this feature might be relevant.

          TypeScript 3.8 adds a new syntax for type-only imports and exports.

          import type { SomeThing } from "./some-module.js";
          export type { SomeThing };

          需要單獨引入types, 于是把代碼改為:

          image.png

          同時要注意, 如果一個文件有有多個導出, 也要分開引入:

          image.png

          唯一痛苦的是: 全局都需要改一遍, 體力活。

          至此,typeings 問題完美解決。

          5. 無法識別 svg

          我們在使用 svg 作為圖標組件的時候, 一般是:

          import Icon from '@ant-design/icons';
          import ErrorSvg from '@/assets/ico_error.svg';

          const ErrorIcon = (props: any) => <Icon component={ErrorSvg} />;

          // ...
          <ErrorIcon />

          瀏覽器報錯:

          image.png
          error occurred in the </src/assets/ico_error.svg> component

          很明顯的看到, 這里是把文件路徑作為組件了。

          現(xiàn)在要做的是:把這個文件路徑, 換成可以識別的組件。

          搜索一番, 找到了個插件:vite-plugin-react-svg

          加入配置:

          const reactSvgPlugin = require('vite-plugin-react-svg');

          plugins: [
            reactSvgPlugin(),
          ],
          import MyIcon from './svgs/my-icon.svg?component';

          function App({
            return (
              <div>
                <MyIcon />
              </div>

            );
          }

          需要注意的是:引入的 svg 文件需要加 ?component 作為后綴。

          看了一下源碼, 這個后綴是用來作為標識符的,

          image.png

          如果后綴匹配上是component,  就解析文件, 并緩存, 最后返回結(jié)果:

          image.png

          知道原理之后, 就需要把全部的 .svg => .svg?component

          vscode 一鍵替換就可以, 不過注意別把 node_module 里面的也替換了。

          6. global 未定義

          image.png

          global 是 Node里面的變量, 會在客戶端報錯 ?

          一層層看下去, 原來是引入的第三方包使用了global。

          看 vite 文檔里提到了 Client Types:

          image.png

          追加到 tsconfig 里面:

           "compilerOptions": {
              "types": ["node""jest""vite/client"],
           }

          然后, 并沒有什么亂用。。。

          image.png

          沒辦法, 只得祭出 window 大法。

          在入口index.tsx 里面加上:

          (window as any).global = window;

          刷新, 好了。

          image.png

          7. [未解決] 替代HtmlWebpackPlugin

          還需要注入一些外部變量, 修改入口html, favicon, title 之類。

          找到一個插件:vite-plugin-singlefile

          不過并沒有什么用。

          有了解的同學請留言賜教。

          至此, 整個 app 已經(jīng)能在本地跑起來了, build 也沒問題。

          7. 線上打包構(gòu)建時, 內(nèi)存溢出

          本地能跑起來, 打包也沒問題, 后面當然是放到線上跑一跑啦。

          立刻安排!

          memory.png

          內(nèi)存不足, 我就給你加點:

          image.png
          success.png

          搞定!

          關于 Vite 開發(fā)、打包上線的一些思考

          從實際使用來看, vite 在一些功能上還是無法完全替代 webpack。

          畢竟是后起之秀, 相關的生態(tài)還需要持續(xù)完善。

          個人認為,目前一種比較穩(wěn)妥的方式是:

          • 保留 webpack dev & build 的能力, vite 僅作為開發(fā)的輔助

          等相關工具再完善一些, 再考慮完全遷移過來。

          相關代碼和結(jié)論

          一個完整的 Vite demo

          倉庫地址:https://github.com/beMySun/react-hooks-i18n-template/tree/test-wp2vite

          image.png

          業(yè)務項目的 vite.config.js 完整配置

          import { defineConfig } from 'vite';
          import reactRefresh from '@vitejs/plugin-react-refresh';
          import legacyPlugin from '@vitejs/plugin-legacy';
          import { resolve } from 'path';

          const fs = require('fs');
          const lessToJS = require('less-vars-to-js');
          const themeVariables = lessToJS(fs.readFileSync(resolve(__dirname, './src/antd-custom.less'), 'utf8'));
          const reactSvgPlugin = require('vite-plugin-react-svg');

          // https://cn.vitejs.dev/config/
          export default defineConfig({
            base'./',
            root'./',
            resolve: {
              alias: {
                'react-native''react-native-web',
                '@': resolve(__dirname, 'src'),
              },
            },
            define: {
              'process.env.REACT_APP_IS_LOCAL''\'true\'',
              'window.__CID__'JSON.stringify(process.env.cid || 'id'),
            },
            server: {
              port8080,
              proxy: {
                '/api': {
                  target'https://stoku.test.shopee.co.id/',
                  changeOrigintrue,
                  cookieDomainRewrite: {
                    'stoku.test.shopee.co.id''localhost',
                  },
                },
              },
            },
            build: {
              target'es2015',
              minify'terser',
              manifestfalse,
              sourcemapfalse,
              outDir'build',
              rollupOptions: {},
            },
            esbuild: {},
            optimizeDeps: {},
            plugins: [
              // viteSingleFile({
              //   title: 'dynamic title', // doesn't work
              // }),
              reactSvgPlugin(),
              reactRefresh(),
              legacyPlugin({
                targets: [
                  'Android > 39',
                  'Chrome >= 60',
                  'Safari >= 10.1',
                  'iOS >= 10.3',
                  'Firefox >= 54',
                  'Edge >= 15',
                ],
              }),
              // vitePluginImp({
              //   libList: [
              //     {
              //       libName: 'antd',
              //       style: (name) => `antd/es/${name}/style`,
              //     },
              //   ],
              // }),
            ],
            css: {
              preprocessorOptions: {
                less: {
                  modifyVars: {
                    hack`true;@import '${resolve('./src/vars.less')}';`,
                    ...themeVariables,
                  },
                  javascriptEnabledtrue,
                },
              },
            },
          });

          最后

          使用 Vite 能大幅縮短項目構(gòu)建時間,提升開發(fā)效率。

          不過也要結(jié)合項目的實際情況,合理取舍。

          對于我的這個項目而言,把 Vite 作為輔助開發(fā)的一種方式,還是挺有用的。

          期待 Vite 能繼續(xù)完善,為研發(fā)提效。

          好了, 內(nèi)容大概就這么多, 希望對大家有所幫助。


          最后



          如果你覺得這篇內(nèi)容對你挺有啟發(fā),我想邀請你幫我三個小忙:

          1. 點個「在看」,讓更多的人也能看到這篇內(nèi)容(喜歡不點在看,都是耍流氓 -_-)

          2. 歡迎加我微信「 sherlocked_93 」拉你進技術群,長期交流學習...

          3. 關注公眾號「前端下午茶」,持續(xù)為你推送精選好文,也可以加我為好友,隨時聊騷。


          點個在看支持我吧,轉(zhuǎn)發(fā)就更好了



          瀏覽 61
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  婷婷成人免费视频 | 精品91秘 一区二区三区 | 爱草逼爱草逼爱草逼爱草逼爱草逼爱草逼 | 欧美人与禽性XXXXX杂性 欧美日韩一区二区三区,麻豆 | 一道本一区二区日韩一区二区 |