webpack介紹(翻譯)

前端自動(dòng)化

  • 您需要跟蹤文件應(yīng)該加載的正確順序,包括哪些文件依賴于哪些其他文件,并確保不包含您不需要的任何文件。
  • 過多的 <script> 會(huì)增多網(wǎng)絡(luò)需求
  • 這些都可以自動(dòng)化

為什么要使用webpack

  • 新工具具有很多新特性,避免了一些前輩的問題
  • 使用簡(jiǎn)單,如果僅用來打包js文件不使其他花哨的東西,甚至不用過多的配置
  • 插件系統(tǒng)完善,你可以作為工具使用它

開始使用

  • npm init
  • npm install webpack -D / -D 意味這作為依賴安裝,相當(dāng)于 --save-dev
  • npm install lodash -S / -S 意味著--save
  • main.js
var map=require("lodash/map");
var square=function(n){
    return n*n
}
console.log(map([1,2,3,4,5,6], square));
  • node main.js

如何使用webpack來打包呢?下面循序漸進(jìn)的為大家介紹

1. 使用webpack命令行

開始使用webpack而不浪費(fèi)時(shí)間在配置文件上的最簡(jiǎn)單的方法就是從命令行運(yùn)行它。 無需使用配置文件的webpack命令的最簡(jiǎn)單版本就是輸入文件路徑和輸出文件路徑。 Webpack將從該輸入文件中讀取,跟蹤其依賴關(guān)系樹,將所有文件合并到一個(gè)文件中,并將文件輸出到您指定為輸出路徑的位置。 對(duì)于這個(gè)例子,我們的輸入路徑是main.js,我們要將捆綁的文件輸出到bundle.js。 所以,讓我們創(chuàng)建一個(gè)npm腳本來做到這一點(diǎn)(我們沒有在全球安裝webpack,所以我們不能直接從命令行運(yùn)行它)。 在package.json中,編輯<script>部分,如下所示:

  "scripts": {
    "build": "webpack src/main.js dist/bundle.js",
  }

在探索webpack之前,我們?cè)賮硪槐?,通過在重建之前刪除dist目錄及其內(nèi)容,并添加一些腳本來執(zhí)行我們的bundle,讓我們的構(gòu)建腳本變得更加專業(yè)。 我們需要做的第一件事是安裝del-cli,以便我們可以刪除目錄,而不會(huì)使不使用與我們相同的操作系統(tǒng)的人員(不要因?yàn)槭褂肳indows而討厭我); npm安裝del-cli -D應(yīng)該做的伎倆。 然后,我們將將npm腳本更新為以下內(nèi)容:

scripts": {
    "prebuild": "del-cli dist -f",
    "build": "webpack src/main.js dist/bundle.js",
    "execute": "node dist/bundle.js",
    "start": "npm run build -s && npm run execute -s"
  }

我們保持build與以前一樣,但現(xiàn)在我們有prebuild來做一些清理,這將在build之前運(yùn)行,每次build被告知運(yùn)行。 我們還有execute,它使用Node.js來執(zhí)行捆綁的腳本,我們可以使用start使用一個(gè)命令來完成所有操作(-s位只是使npm腳本不輸出為 無用的東西到控制臺(tái))。 繼續(xù)運(yùn)行npm開始。 您應(yīng)該看到webpack的輸出,快速跟隨我們的平方陣列,顯示在您的控制臺(tái)。 恭喜! 剛剛完成了我之前提到的存儲(chǔ)庫(kù)的example1分支中的所有內(nèi)容。

2. 使用配置的webpack

與使用webpack命令行一樣有趣,一旦你開始使用更多的webpack的功能,你將要遠(yuǎn)離傳遞所有的選項(xiàng)通過命令行,而是使用一個(gè)配置文件 ,這將具有更多的能力,但由于它是用JavaScript編寫的,它們也將更加易讀。
所以,我們來創(chuàng)建一個(gè)配置文件。 在項(xiàng)目的根目錄中創(chuàng)建名為webpack.config.js的新文件。 這是默認(rèn)情況下webpack將要查找的文件名,但如果要將配置文件命名為其他目錄或?qū)⑵浞旁诓煌哪夸浿?,則可以將--config [filename]選項(xiàng)傳遞給webpack。
對(duì)于本教程,我們將使用標(biāo)準(zhǔn)文件名,現(xiàn)在我們將嘗試使其工作方式與使用命令行一樣。 為此,我們需要將以下代碼添加到配置文件中:

module.exports = {
    entry: './src/main.js',
    output: {
        path: './dist',
        filename: 'bundle.js'
    }
};

3. 學(xué)習(xí)使用loader

使用webpack處理文件有兩種方式,loader或者插件,先討論loader,loader被用來轉(zhuǎn)換或者操作文件指定類型。我們可以對(duì)一個(gè)文件使用多個(gè)loader,例如我們可以先對(duì)一個(gè)文件進(jìn)行Eslint操作之后用Babel把他轉(zhuǎn)化為ES5,如果ESLint給出警告,竟會(huì)打印出警告信息,如果報(bào)錯(cuò),就不會(huì)繼續(xù)運(yùn)行后面的loader。
下面用ES2015語(yǔ)法來下寫main2.js

import { map } from 'lodash';

console.log(map([1,2,3,4,5,6], n => n*n));

上面代碼運(yùn)用ES2015寫法,用了import 代替 require (import {map} from loadsh 這樣寫會(huì)把整個(gè)loadsh引入,當(dāng)然也可以用 import map from 'lodash/map) ;用箭頭函數(shù)代替了function。這些都是ES2015語(yǔ)法

我們需要編譯使之在一些老舊瀏覽器中運(yùn)行良好,為此我們需要使用Babel和webpack來運(yùn)行編譯。
需要的loader:

  1. babel-core(Babel 核心功能,完成大部分工作)
  2. babel-loader(webpack提供的和babel-core的接口)
  3. babel-preset-es2015(告訴babeles2015編譯為ES5的規(guī)則)
  4. babel-plugin-transform-runtime , babel-polyfill(這兩者都改變??了Babel向您的代碼庫(kù)添加polyfills和helper函數(shù)的方式,盡管它們有所不同,因此它們適合于不同類型的項(xiàng)目。)
    安裝這些包,然后更新webpack.config.js代碼
module.exports = {
    entry: './src/main.js',
    output: {
        path: './dist',
        filename: 'bundle.js'
    },
    module: {
        rules: [
            …
        ]
    }
};

我們看到增加了module,module下兩個(gè)有一個(gè)rules屬性,這是一個(gè)數(shù)組,對(duì)于每組rule,我們?cè)O(shè)置兩個(gè)選項(xiàng)testloader.

  1. test用來測(cè)試文件類型,通常是一個(gè)正則表達(dá)式,例如/\.js$/就是以js結(jié)尾的文件名,/\.jsx?$/匹配以js或jsx結(jié)尾的文件.
  2. loader用來指定運(yùn)用哪些loader處理匹配到的文件。通過傳入帶有加載器名稱的字符串來指定,用!分隔。例如babel-loader!eslint-loader,webpack從右向做開始編譯,先經(jīng)過eslint再經(jīng)過babel-loader,如果loader有特殊選項(xiàng)你想指定,你可以使用babel-loader?fakeoption=true!eslint-loader這種形式,用option形式。
module:{
    rules:[
        {
            test:/\.jsx?$/,
            loader:'babel-core',
            exclude: /node_modules/,
            option:{
                plugins: ['transform-runtime'],
                presets: ['es2015']  
            }
        }
    ]
}

我們需要設(shè)置預(yù)設(shè),使所有的ES2015功能都將轉(zhuǎn)換為ES5,我們還將設(shè)置使用我們安裝的轉(zhuǎn)換運(yùn)行時(shí)插件。如前所述,這個(gè)插件是沒有必要的,但它在那里告訴你如何做到這一點(diǎn)。另一種方法是使用.babelrc文件來設(shè)置這些選項(xiàng),但是我無法向您展示如何在webpack中執(zhí)行此操作。一般來說,我建議使用.babelrc,但我們將在此項(xiàng)目中保留配置。exclude文件排除了node_modules文件夾.

4. 使用 Handlebars loader

使用handlebars模板的loader,僅僅舉個(gè)例子

  1. 安裝handlebars以及他的loadercnpm install handlebars handlebars-loader -D
  2. import template from 'handlebars-loader!./numberlist.hbs或者使用loader{ test: /\.hbs$/, loader: 'handlebars-loader' }.
  3. 使用npm start就會(huì)打印出li標(biāo)簽

5. 學(xué)習(xí)使用插件

除了loader之外,插件是將自定義功能安裝到Webpack中。您可以自由地將它們添加到Webpack工作流程中,因?yàn)樗鼈儾粌H限于在加載特定文件類型時(shí)被使用;它們幾乎可以在任何地方注入,因此能夠做得更多.下面舉兩個(gè)關(guān)于插件的例子.

  1. HTML Webpack Plugin
    1. npm i http-server html-webpack-plugin -D
    2. package.json
"scripts": {
    "prebuild": "del-cli dist -f",
    "build": "webpack",
    "server": "http-server ./dist",
    "start": "npm run build -s && npm run server -s"
},
3. webpack.config.js
const path = require('path');
var HtmlWebpackPlugin=require("html-webpack-plugin")
module.exports = {
    entry: [
    'babel-polyfill',
    './src/main.js'
    ],
    output: {
        path: path.resolve(__dirname, './dist'),
        filename: 'bundle.js'
    },
    module:{
        rules:[
            {
                test:/\.jsx?$/,
                loader:'babel-loader',
                exclude: /node_modules/,
                options:{
                    plugins: ['transform-runtime'],
                    presets: ['es2015']  
                }
            },
            { 
                test: /\.hbs$/, 
                loader: 'handlebars-loader'
             }
        ]
    },
    plugins:[
        new HtmlWebpackPlugin()
    ]
};

我們所做的兩個(gè)更改是將新安裝的插件導(dǎo)入文件的頂部,然后在配置對(duì)象的末尾添加一個(gè)plugins,我們?cè)谶@個(gè)插件中傳入新實(shí)例。
在這一點(diǎn)上,我們沒有將任何選項(xiàng)傳遞給插件,所以它使用的標(biāo)準(zhǔn)模板不包括很多,但它包含了我們的捆綁腳本。如果您運(yùn)行npm啟動(dòng),然后訪問瀏覽器中的URL,您將看到一個(gè)空白頁(yè)面,但是如果您打開開發(fā)人員的工具,則應(yīng)該會(huì)將HTML輸出到控制臺(tái)。

我們不應(yīng)讓其只從控制臺(tái)輸出,應(yīng)該讓他出現(xiàn)在HTML中,在src下新建index.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
    <h2>This is my Index.html Template</h2>
    <div id="app-container"></div>
</body>
</html>

注意我們通過向ejs文件傳遞插件中參數(shù)
沒有指定應(yīng)該添加腳本的位置。這是因?yàn)槟J(rèn)情況下,該插件會(huì)將腳本添加到body標(biāo)簽的末尾。

webpack.config.js中增加下面選項(xiàng)

 plugins: [
        new HtmlwebpackPlugin({
            title: 'Intro to webpack',
            template: 'src/index.html'
        })
    ]

我在嘗試按照上面例子寫demo的時(shí)候發(fā)現(xiàn)并不能將hbs模板插入到html中不知道為啥子.
我知道為啥子了,window.onload!!!

6. 使用懶加載

有一件事我非常喜歡與RequireJS,不能很好地使用Browserify(盡管可能)是懶惰加載模塊。一個(gè)大規(guī)模的JavaScript文件將有助于限制所需的HTTP請(qǐng)求數(shù)量,但實(shí)際上保證下載的代碼不一定在該會(huì)話中被訪問者使用。
Webpack有一種方法可以將捆綁分割成可以進(jìn)行延遲加載的大塊,甚至不需要任何配置。所有你需要做的是以兩種方式之一編寫代碼,webpack將處理其余的代碼。 Webpack為您提供了兩種方法:一種基于CommonJS,另一種基于AMD。要使用CommonJS來懶惰加載模塊,你可以這樣寫:

require.ensure(["module-a", "module-b"], function(require) {
    var a = require("module-a");
    var b = require("module-b");
    // …
});

使用require.ensure,這將確保模塊可用(但不執(zhí)行),并傳遞一個(gè)模塊名稱數(shù)組,然后傳回一個(gè)回調(diào)。要在該回調(diào)中實(shí)際使用該模塊,您需要使用傳遞給回調(diào)的參數(shù)來明確地要求它。

AMD版本

require(["module-a", "module-b"], function(a, b) {
    // …
});
import { map } from 'lodash';

let numbers = map([1,2,3,4,5,6], n => n*n);

setTimeout( () => {
    require(['./numberlist.hbs'], template => {
        document.getElementById("app-container").innerHTML = template({numbers});
    })
}, 2000);

現(xiàn)在,如果您運(yùn)行npm start,您將看到生成另一個(gè)文件,它應(yīng)該命名為1.bundle.js。如果您在瀏覽器中打開頁(yè)面并打開您的開發(fā)工具來觀看網(wǎng)絡(luò)流量,您會(huì)看到延遲2秒后,新文件將被加載并執(zhí)行。這并不是很難實(shí)現(xiàn),可以使用戶的體驗(yàn)好多了。
請(qǐng)注意,這些子包或塊包含其所有依賴關(guān)系,除了每個(gè)子包中包含的子包。 (您可以有多個(gè)條目,每個(gè)條目都延遲加載此塊,因此,每個(gè)父項(xiàng)都加載不同的依賴項(xiàng)。)

7. Creating A Vendor Chunk

我們來談一談可以做的一個(gè)優(yōu)化:wendor。你可以定義要構(gòu)建的單獨(dú)的包,該包將存儲(chǔ)不太可能更改的“常用”或第三方代碼。這允許訪問者將庫(kù)從應(yīng)用程序代碼緩存在一個(gè)單獨(dú)的文件中,以便在更新應(yīng)用程序時(shí)不需要再次下載這些庫(kù)。
為此,我們將使用一個(gè)名為CommonsChunkPlugin的webpack附帶的插件。它被包含,我們不需要安裝任何東西;我們需要做的是對(duì)webpack.config.js進(jìn)行一些編輯

var HtmlwebpackPlugin = require('html-webpack-plugin');
var UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin');
var CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');

module.exports = {
    entry: {
        vendor: ['babel-polyfill', 'lodash'],
        main: './src/main.js'
    },
    output: {
        path: './dist',
        filename: 'bundle.js'
    },
    module: {
        rules: [
            {
                test: /\.jsx?$/, loader: 'babel-loader', exclude: /node_modules/,
                options: { plugins: ['transform-runtime'], presets: ['es2015'] }
            },
            { test: /\.hbs$/, loader: 'handlebars-loader' }
        ]
    },
    plugins: [
        new HtmlwebpackPlugin({
            title: 'Intro to webpack',
            template: 'src/index.html'
        }),
        new UglifyJsPlugin({
            beautify: false,
            mangle: { screw_ie8 : true },
            compress: { screw_ie8: true, warnings: false },
            comments: false
        }),
        new CommonsChunkPlugin({
            name: "vendor",
            filename: "vendor.bundle.js"
        })
    ]
};

第3行是我們導(dǎo)入插件的地方。然后,在入口部分,我們使用不同的設(shè)置(對(duì)象字面值)來指定多個(gè)入口點(diǎn)。vendor中包括polyfill以及Lodash,我們將主條目文件放入主條目。然后,我們只需要將CommonsChunkPlugin添加到插件部分,將vendor指定為基礎(chǔ)的塊,并指定vendor將存儲(chǔ)在名為vendor.bundle.js的文件中。
通過指定vendor,此插件會(huì)將其他條目文件中指定的所有依賴項(xiàng)提取到該供應(yīng)商塊中。如果這里沒有指定塊名,它將根據(jù)條目之間共享的依賴關(guān)系創(chuàng)建一個(gè)單獨(dú)的文件。
運(yùn)行webpack時(shí),現(xiàn)在應(yīng)該會(huì)看到三個(gè)JavaScript文件:bundle.js,1.bundle.js和vendor.bundle.js。您可以運(yùn)行npm開始,并在瀏覽器中查看結(jié)果(如果需要)??雌饋韜ebpack甚至?xí)汛蟛糠肿约旱拇a用于處理不同模塊的加載到vendor中.

我表示并沒有看到1.bundle.js這個(gè)文件

結(jié)語(yǔ)

當(dāng)然webpack不僅僅能實(shí)現(xiàn)上述功能,他還能輕松實(shí)現(xiàn)CSS模塊,高速緩存清除散列,圖像優(yōu)化,希望在以后的學(xué)習(xí)多多運(yùn)用。( Webpack enables easy CSS modules, cache-busting hashes, image optimization and much much more — so much that even if I wrote a massive book on the subject, I couldn’t show you everything, and by the time I finished writing that book, most (if not all) of it would be outdated! So, give webpack a try today, and let me know if it improves your workflow. God bless and happy coding!)

原文鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 作者:小 boy (滬江前端開發(fā)工程師)本文原創(chuàng),轉(zhuǎn)載請(qǐng)注明作者及出處。原文地址:https://www.smas...
    iKcamp閱讀 2,830評(píng)論 0 18
  • 無意中看到zhangwnag大佬分享的webpack教程感覺受益匪淺,特此分享以備自己日后查看,也希望更多的人看到...
    小小字符閱讀 8,371評(píng)論 7 35
  • 寫在開頭 先說說為什么要寫這篇文章, 最初的原因是組里的小朋友們看了webpack文檔后, 表情都是這樣的: (摘...
    Lefter閱讀 5,445評(píng)論 4 31
  • GitChat技術(shù)雜談 前言 本文較長(zhǎng),為了節(jié)省你的閱讀時(shí)間,在文前列寫作思路如下: 什么是 webpack,它要...
    蕭玄辭閱讀 12,894評(píng)論 7 110
  • 最近在學(xué)習(xí) Webpack,網(wǎng)上大多數(shù)入門教程都是基于 Webpack 1.x 版本的,我學(xué)習(xí) Webpack 的...
    My_Oh_My閱讀 8,334評(píng)論 40 247

友情鏈接更多精彩內(nèi)容