日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
WebBundlerCheatSheet,選擇合適的構(gòu)建打包工具

Web Bundler CheatSheet | Web 構(gòu)建與打包工具盤點(diǎn)

創(chuàng)新互聯(lián)公司專業(yè)為企業(yè)提供同心網(wǎng)站建設(shè)、同心做網(wǎng)站、同心網(wǎng)站設(shè)計(jì)、同心網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)與制作、同心企業(yè)網(wǎng)站模板建站服務(wù),十多年同心做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。

工欲善其事,必先利其器,當(dāng)我們準(zhǔn)備開始某個(gè) Web 相關(guān)的項(xiàng)目時(shí),合適的腳手架會(huì)讓我們事半功倍。在 2016-我的前端之路:工具化與工程化一文中,我們討論了工具化與工程化相關(guān)的內(nèi)容,其中重要的章節(jié)就是關(guān)于所謂的打包工具。Grunt、Glup 屬于 Task Runner,即任務(wù)執(zhí)行器; 實(shí)際上,npm package.json 中定義的腳本也可以看做 Task Runner,而 Rollup,Parcel 以及 Webpack 則是屬于 Bundler,即打包工具。

尺有所短,寸有所長,不同的構(gòu)建工具有其不同的適用場(chǎng)景。Webpack 是非常優(yōu)秀的構(gòu)建與打包工具,但是其提供了基礎(chǔ)且復(fù)雜的功能支持,使得并不適用于全部的場(chǎng)景。Parcel 這樣的零配置打包工具適合于應(yīng)用型的原型項(xiàng)目構(gòu)建,而 Rollup 或者 Microbundle 適合于庫的打包,Backpack 則能夠幫我們快速構(gòu)建 Node.js 項(xiàng)目。筆者在本文中列舉討論的僅是日常工作中會(huì)使用的工具,更多的 Browserify、Fusebox 等等構(gòu)建工具查看 Web 構(gòu)建與打包工具資料索引或者現(xiàn)代 Web 開發(fā)實(shí)戰(zhàn)/進(jìn)階篇。

Parcel

Parcel 是著名的零配置的應(yīng)用打包工具,在 TensorflowJS 或者 gh-craft 等算法實(shí)驗(yàn)/游戲場(chǎng)景構(gòu)建中,都能夠快速地搭建應(yīng)用。

 
 
 
 
  1. # 安裝 Parcel
  2. $ npm install -g parcel-bundler
  3. # 啟動(dòng)開發(fā)服務(wù)器
  4. $ parcel index.html
  5. # 執(zhí)行線上編譯
  6. $ parcel build index.js
  7. # 指定編譯路徑
  8. $ parcel build index.js -d build/output

Parcel 會(huì)為我們自動(dòng)地下載安裝依賴,并且內(nèi)置了 ES、SCSS 等常見的處理器。在 fe-boilerplate 中提供了 React, React & TypeScript, Vue.js 等 Parcel 常見的示例,這里以 React 為例,首先定義組件與渲染:

 
 
 
 
  1. // index.js
  2. import React from 'react';
  3. import ReactDOM from 'react-dom';
  4. import logo from '../public/logo.svg';
  5. import './index.css';
  6. const App = () => (
  7.   
  8.     
  9.     Hello Parcel x React
  10.   
  • );
  • ReactDOM.render(, document.getElementById('root'));
  • // Hot Module Replacement
  • if (module.hot) {
  •   module.hot.accept();
  • }
  • 然后定義入口的 index.html 文件:

     
     
     
     
    1.   
    2.   
    3.   
    4.   Parcel React Example
    5.   
  •   
  • 然后使用 parcel index.html 運(yùn)行開發(fā)服務(wù)器即可。Parcel 中同樣也是支持異步加載的,假設(shè)我們將部分代碼定義在 someModule.js 文件中,然后在用戶真實(shí)需要時(shí)再進(jìn)行加載:

     
     
     
     
    1. // someModule.js
    2. console.log('someModule.js loaded');
    3. module.exports = {
    4.   render: function(element) {
    5.     element.innerHTML = 'You clicked a button';
    6.   }
    7. };

    在入口文件中使用 import 進(jìn)行異步加載:

     
     
     
     
    1. console.log('index.js loaded');
    2. window.onload = function() {
    3.   document.querySelector('#bt').addEventListener('click', function(evt) {
    4.     console.log('Button Clicked');
    5.     import('./someModule').then(function(page) {
    6.       page.render(document.querySelector('.holder'));
    7.     });
    8.   });
    9. };

    ***值得一提的是,Parcel 內(nèi)建支持 WebAssembly 與 Rust,通過簡(jiǎn)單的 import 導(dǎo)入,即可以使用 WASM 模塊:

     
     
     
     
    1. // synchronous import
    2. import {add} from './add.wasm';
    3. console.log(add(2, 3));
    4. // asynchronous import
    5. const {add} = await import('./add.wasm');
    6. console.log(add(2, 3));
    7. // synchronous import
    8. import {add} from './add.rs';
    9. console.log(add(2, 3));
    10. // asynchronous import
    11. const {add} = await import('./add.rs');
    12. console.log(add(2, 3));

    這里 add.rs 是使用 Rust 編寫的簡(jiǎn)單加法計(jì)算函數(shù):

     
     
     
     
    1. #[no_mangle]
    2. pub fn add(a: i32, b: i32) -> i32 {
    3.   return a + b
    4. }

    Rollup 是較為為純粹的模塊打包工具,其相較于 Parcel 與 Webpack 等,更適合于構(gòu)建 Library,譬如 React、Vue.js、Angular、D3、Moment、Redux 等一系列優(yōu)秀的庫都是采用 Rollup 進(jìn)行構(gòu)建。。Rollup 能夠?qū)凑?ESM(ES2015 Module)規(guī)范編寫的源碼構(gòu)建輸出為 IIFE、AMD、CommonJS、UMD、ESM 等多種格式,并且其較早地支持 Tree Shaking,Scope Hoisting 等優(yōu)化特性,保證模塊的簡(jiǎn)潔與高效。這里我們使用的 Rollup 示例配置項(xiàng)目存放在了 fe-boilerplate/rollup。最簡(jiǎn)單的 rollup.config.js 文件配置如下:

     
     
     
     
    1. export default {
    2.   // 指定模塊入口
    3.   entry: 'src/scripts/main.js',
    4.   // 指定包體文件名
    5.   dest: 'build/js/main.min.js',
    6.   // 指定文件格式
    7.   format: 'iife',
    8.   // 指定 SourceMap 格式
    9.   sourceMap: 'inline'
    10. };

    如果我們只是對(duì)簡(jiǎn)單的 sayHello 函數(shù)進(jìn)行打包,那么輸出的文件中也只是會(huì)簡(jiǎn)單地連接與調(diào)用,并且清除未真實(shí)使用的模塊:

     
     
     
     
    1. (function() {
    2.   'use strict';
    3.   ...
    4.   function sayHelloTo(name) {
    5.     ...
    6.   }
    7.   ...
    8.   const result1 = sayHelloTo('Jason');
    9.   ...
    10. })();
    11. //# sourceMappingURL=data:application/json;charset=utf-8;base64,...

    Rollup 同樣具有豐富的插件系統(tǒng),在 fe-boilerplate/rollup 中我們也引入了常見的別名、ESLint、環(huán)境變量定義、包體壓縮與分析等插件。這里我們以最常用的 Babel 與 TypeScript 為例,如果我們需要在項(xiàng)目中引入 Babel,則同樣在根目錄配置 .babelrc 文件,然后引入 rollup-plugin-babel 插件即可:

     
     
     
     
    1. import { rollup } from 'rollup';
    2. import babel from 'rollup-plugin-babel';
    3. rollup({
    4.   entry: 'main.js',
    5.   plugins: [
    6.     babel({
    7.       exclude: 'node_modules/**'
    8.     })
    9.   ]
    10. }).then(...)

    對(duì)于 TypeScript 則是引入 rollup-plugin-typescript 插件:

     
     
     
     
    1. import typescript from 'rollup-plugin-typescript';
    2. export default {
    3.   entry: './main.ts',
    4.   plugins: [typescript()]
    5. };

    Microbundle 則是 Developit 基于 Rollup 封裝的零配置的輕量級(jí)打包工具,其目前已經(jīng)內(nèi)建支持 TypeScript 與 Flow,不需要額外的配置;筆者在 js-swissgear/x-fetch 項(xiàng)目的打包中也使用了該工具。

     
     
     
     
    1. {
    2.   "scripts": {
    3.     "build": "microbundle",
    4.     "dev": "microbundle watch"
    5.   }
    6. }
    • index.js 是 CommonJS 模塊,是 Node.js 內(nèi)置的模塊類型,使用類似于 require('MyModule') 語法導(dǎo)入
    • index.m.js 是 ECMAScript 模塊,使用類似于 import MyModule from 'my-module' 語法導(dǎo)入
    • index.umd.js 是 UMD 模塊
    • index.d.ts 是 TypeScript 的類型聲明文件

    Webpack

    作為著名的打包工具,Webpack 允許我們指定項(xiàng)目的入口地址,然后自動(dòng)將用到的資源,經(jīng)由 Loader 與 Plugin 的轉(zhuǎn)換,打包到包體文件中。Webpack 相關(guān)的項(xiàng)目模板可以參考:fe-boilerplate/react-webpack, fe-boilerplate/react-webpack-ts, fe-boilerplate/vue-webpack 等。

    Webpack 目前也支持零配置運(yùn)行

     
     
     
     
    1. $ npm install webpack webpack-cli webpack-dev-server --save-dev
    2. "scripts": {
    3.   "start": "webpack-dev-server --mode development",
    4.   "build": "webpack --mode production"
    5. },

    基礎(chǔ)配置

     
     
     
     
    1. const config = {
    2.   // 定義入口
    3.   entry: {
    4.     app: path.join(__dirname, 'app')
    5.   },
    6.   // 定義包體文件
    7.   output: {
    8.     // 輸出目錄
    9.     path: path.join(__dirname, 'build'),
    10.     // 輸出文件名
    11.     filename: '[name].js'
    12.     // 使用 hash 作為文件名
    13.     // filename: "[name].[chunkhash].js",
    14.   },
    15.   // 定義如何處理
    16.   module: {
    17.     rules: [
    18.       {
    19.         test: /\.js$/,
    20.         use: 'babel-loader',
    21.         exclude: /node_modules/
    22.       }
    23.     ]
    24.   },
    25.   // 添加額外插件操作
    26.   plugins: [new webpack.DefinePlugin()]
    27. };

    Webpack 同樣支持添加多個(gè)配置:

     
     
     
     
    1. module.exports = [{
    2.   entry: './app.js',
    3.   output: ...,
    4.   ...
    5. }, {
    6.   entry: './app.js',
    7.   output: ...,
    8.   ...
    9. }]

    我們代碼中的 require 與 import 解析規(guī)范,則由 resolve 模塊負(fù)責(zé),其包含了擴(kuò)展、別名、模塊等部分:

     
     
     
     
    1. const config = {
    2.   resolve: {
    3.     alias: {
    4.       /*...*/
    5.     },
    6.     extensions: [
    7.       /*...*/
    8.     ],
    9.     modules: [
    10.       /*...*/
    11.     ]
    12.   }
    13. };

    資源加載

     
     
     
     
    1. const config = {
    2.   module: {
    3.     rules: [
    4.       {
    5.         // **Conditions**
    6.         test: /\.js$/, // Match files
    7.         enforce: 'pre', // "post" too
    8.         // **Restrictions**
    9.         include: path.join(__dirname, 'app'),
    10.         exclude: path => path.match(/node_modules/),
    11.         // **Actions**
    12.         use: 'babel-loader'
    13.       }
    14.     ]
    15.   }
    16. };
    17. // Process foo.png through url-loader and other matches
    18. import 'url-loader!./foo.png';
    19. // Override possible higher level match completely
    20. import '!!url-loader!./bar.png';

    babel-loader 或者 awesome-typescript-loader 來處理 JavaScript 或者 TypeScript 文件

     
     
     
     
    1. /******/ (function(modules) { // webpackBootstrap
    2. ...
    3. /* 0 */
    4. /***/ (function(module, __webpack_exports__, __webpack_require__) {
    5. "use strict";
    6. __webpack_require__.r(__webpack_exports__);
    7. /* harmony default export */ __webpack_exports__["default"] = ((text = "Hello world") => {
    8.   const element = document.createElement("div");
    9.   element.innerHTML = text;
    10.   return element;
    11. });
    12. /***/ })
    13. /******/ ]);

    use: ["style-loader", "css-loader"] css-loader 會(huì)自動(dòng)地解析 @import 與 url(),而 style-loader 則會(huì)將 CSS 注入到 DOM 中,并且實(shí)現(xiàn) HMR 的特性,而對(duì)于 SASS、LESS 等 CSS 預(yù)處理器,也有專門的 sass-loader 或者 less-loader 來處理;在生產(chǎn)環(huán)境下,我們也常常會(huì)將 CSS 抽取到獨(dú)立的樣式文件中,此時(shí)就可以使用 mini-css-extract-plugin (MCEP) 等工具。同樣,我們可以使用 url-loader/file-loader 來處理圖片等資源文件,

    代碼分割

    代碼分割是提升 Web 性能表現(xiàn)的重要分割,我們常做的代碼分割也分為公共代碼提取與按需加載等方式。公共代碼提取即是將第三方渲染模塊或者庫與應(yīng)用本身的邏輯代碼分割,或者將應(yīng)用中多個(gè)模塊間的公共代碼提取出來,劃分到獨(dú)立的 Chunk 中,以方便客戶端進(jìn)行緩存等操作。

    不同于 Webpack 3 中需要依賴 CommonChunksPlugin 進(jìn)行配置,Webpack 4 引入了 SplitChunksPlugin,并為我們提供了開箱即用的代碼優(yōu)化特性,Webpack 會(huì)根據(jù)以下情況自動(dòng)進(jìn)行代碼分割操作:

    • 新的塊是在多個(gè)模塊間共享,或者來自于 node_modules 目錄;
    • 新的塊在壓縮之前的大小應(yīng)該超過 30KB;
    • 頁面所需并發(fā)加載的塊數(shù)量應(yīng)該小于或者等于 5;
    • 初始頁面加載的塊數(shù)量應(yīng)該小于或者等于 3;

    SplitChunksPlugin 的默認(rèn)配置如下:

     
     
     
     
    1. splitChunks: {
    2.     chunks: "async",
    3.     minSize: 30000,
    4.     minChunks: 1,
    5.     maxAsyncRequests: 5,
    6.     maxInitialRequests: 3,
    7.     automaticNameDelimiter: '~',
    8.     name: true,
    9.     cacheGroups: {
    10.         vendors: {
    11.             test: /[\\/]node_modules[\\/]/,
    12.             priority: -10
    13.         },
    14.     default: {
    15.             minChunks: 2,
    16.             priority: -20,
    17.             reuseExistingChunk: true
    18.         }
    19.     }
    20. }

    值得一提的是,這里的 chunks 選項(xiàng)有 initial, async 與 all 三個(gè)配置,上述配置即是分別針對(duì)初始 chunks、按需加載的 chunks 與全部的 chunks 進(jìn)行優(yōu)化;如果將 vendors 的 chunks 設(shè)置為 initial,那么它將忽略通過動(dòng)態(tài)導(dǎo)入的模塊包包含的第三方庫代碼。而 priority 則用于指定某個(gè)自定義的 Cache Group 捕獲代碼的優(yōu)先級(jí),其默認(rèn)值為 0。在 common-chunk-and-vendor-chunk 例子中,我們即針對(duì)入口進(jìn)行優(yōu)化,提取出入口公共的 vendor 模塊與業(yè)務(wù)模塊:

     
     
     
     
    1. {
    2. splitChunks: {
    3.             cacheGroups: {
    4.                 commons: {
    5.                     chunks: "initial",
    6.                     minChunks: 2,
    7.                     maxInitialRequests: 5, // The default limit is too small to showcase the effect
    8.                     minSize: 0 // This is example is too small to create commons chunks
    9.                 },
    10.                 vendor: {
    11.                     test: /node_modules/,
    12.                     chunks: "initial",
    13.                     name: "vendor",
    14.                     priority: 10,
    15.                     enforce: true
    16.                 }
    17.             }
    18.         }
    19. }

    Webpack 的 optimization 還包含了 runtimeChunk 屬性,當(dāng)該屬性值被設(shè)置為 true 時(shí),即會(huì)為每個(gè) Entry 添加僅包含運(yùn)行時(shí)信息的 Chunk; 當(dāng)該屬性值被設(shè)置為 single 時(shí),即為所有的 Entry 創(chuàng)建公用的包含運(yùn)行時(shí)的 Chunk。我們也可以在代碼中使用 import 語句,動(dòng)態(tài)地進(jìn)行塊劃分,實(shí)現(xiàn)代碼的按需加載:

     
     
     
     
    1. // Webpack 3 之后支持顯式指定 Chunk 名
    2. import(/* webpackChunkName: "optional-name" */ './module')
    3.   .then(module => {
    4.     /* ... */
    5.   })
    6.   .catch(error => {
    7.     /* ... */
    8.   });
    9. webpackJsonp([0], {
    10.   KMic: function(a, b, c) {
    11.     ...
    12.   },
    13.   co9Y: function(a, b, c) {
    14.     ...
    15.   },
    16. });

    如果是使用 React 進(jìn)行項(xiàng)目開發(fā),推薦使用 react-loadable 進(jìn)行組件的按需加載,他能夠優(yōu)雅地處理組件加載、服務(wù)端渲染等場(chǎng)景。Webpack 還內(nèi)建支持基于 ES6 Module 規(guī)范的 Tree Shaking 優(yōu)化,即僅從導(dǎo)入文件中提取出所需要的代碼。

    更多關(guān)于 Webpack 的使用技巧可以參閱 Webpack CheatSheet 或者現(xiàn)代 Web 開發(fā)基礎(chǔ)與工程實(shí)踐/Webpack 章節(jié)。

    Backpack

    Backpack 是面向 Node.js 的極簡(jiǎn)構(gòu)建系統(tǒng),受 create-react-app, Next.js 以及 Nodemon 的影響,能夠以零配置的方式創(chuàng)建 Node.js 項(xiàng)目。Backpack 為我們處理了文件監(jiān)控、熱加載、轉(zhuǎn)換、打包等工作,默認(rèn)支持 ECMAScript ***的 async/await, 對(duì)象擴(kuò)展、類屬性等語法。我們可以使用 npm 安裝依賴:

     
     
     
     
    1. $ npm i backpack-core --save

    然后在 package.json 中配置運(yùn)行腳本:

     
     
     
     
    1. {
    2.   "scripts": {
    3.     "dev": "backpack",
    4.     "build": "backpack build"
    5.   }
    6. }

    在 Backend-Boilerplate/node 中可以查看 Backpack 的典型應(yīng)用,我們也可以覆蓋默認(rèn)的 Webpack 配置:

     
     
     
     
    1. // backpack.config.js
    2. module.exports = {
    3.   webpack: (config, options, webpack) => {
    4.     // Perform customizations to config
    5.     // Important: return the modified config
    6.     return config;
    7.   }
    8. };

    或者添加 Babel 插件:

     
     
     
     
    1. {
    2.   "presets": ["backpack-core/babel", "stage-0"]
    3. }

     【本文是專欄作者“張梓雄 ”的原創(chuàng)文章,如需轉(zhuǎn)載請(qǐng)通過與作者聯(lián)系】


    網(wǎng)站欄目:WebBundlerCheatSheet,選擇合適的構(gòu)建打包工具
    標(biāo)題網(wǎng)址:http://www.dlmjj.cn/article/dhiocic.html