webpack簡(jiǎn)介

一拢军、簡(jiǎn)介

webpack 是一個(gè)現(xiàn)代 JavaScript 應(yīng)用程序的靜態(tài)模塊打包器(module bundler)。主要是用來將前端資源打包怔鳖、壓縮茉唉、優(yōu)化。

  • webpack 打包原理:
    當(dāng) webpack 處理應(yīng)用程序時(shí)结执,不會(huì)根據(jù) package.json 文件中的devDependencies 或者 Dependencies 的內(nèi)容對(duì)文件進(jìn)行打包度陆。而是會(huì)根據(jù)入口文件做查詢,加載其所依賴的包模塊献幔,它會(huì)遞歸地構(gòu)建一個(gè)依賴關(guān)系圖(dependency graph)懂傀,其中包含應(yīng)用程序需要的每個(gè)模塊,然后將所有這些模塊打包成一個(gè)或多個(gè) bundle蜡感。
  • 兩個(gè)最核心的概念:
    1.一切皆模塊
    正如js文件可以是一個(gè)模塊(module)一樣蹬蚁,其他的(如css、image或html)文件也可視作模塊郑兴。因此犀斋,你可以require(‘myJSfile.js’)也可以require(‘myCSSfile.css’)。這意味著我們可以業(yè)務(wù)分割成更小的易于管理的片段情连,從而達(dá)到重復(fù)利用的目的叽粹。
    2.按需加載
    傳統(tǒng)的模塊打包工具(module bundlers)最終將所有的模塊編譯生成一個(gè)龐大的bundle.js文件。但是在真實(shí)的app里邊却舀,bundle.js文件可能有10M到15M之大球榆,可能會(huì)導(dǎo)致應(yīng)用一直處于加載中狀態(tài)。因此Webpack使用許多特性來分割代碼然后生成多個(gè)bundle文件禁筏,而且異步加載部分代碼以實(shí)現(xiàn)按需加載持钉。
二、安裝

webpack支持使用npm 或者 yarn 方式進(jìn)行安裝篱昔。不推薦全局安裝 webpack每强,這會(huì)將你項(xiàng)目中的 webpack 鎖定到指定版本,并且在使用不同的 webpack 版本的項(xiàng)目中州刽,可能會(huì)導(dǎo)致構(gòu)建失敗空执。本地安裝可以使我們更容易對(duì)不同的項(xiàng)目進(jìn)行分別升級(jí)。通常穗椅,webpack 通過運(yùn)行一個(gè)或多個(gè) npm scripts辨绊,會(huì)在本地 node_modules 目錄中查找安裝的 webpack:

"scripts": {
    "start": "webpack"
}

如果使用 webpack 4+ 版本,還需要安裝 CLI匹表。webpack-cli 可以允許直接在控制臺(tái)操作webpack命令门坷。終端中輸入 webpack --help宣鄙,可以查看所有的幫助信息。

使用npm安裝:
npm install webpack webpack-cli --save-dev
或者使用yarn安裝:
yarn add webpack webpack-cli -D

三默蚌、webpack基本概念

以以下目錄結(jié)構(gòu)為例來了解以下webpack的基本概念:


  • 入口 entry:在webpack.config.js配置文件中冻晤,通過設(shè)置entry字段的值,指定一個(gè)入口起點(diǎn)(或多個(gè)入口起點(diǎn))绸吸,不配置的話鼻弧,默認(rèn)入口起點(diǎn)為src目錄下的index.js模塊。

默認(rèn)值為:

module.exports = {
    entry: './src'
    //相當(dāng)于
    entry:{ main:"/src/index.js" }
};

單頁(yè)面配置:

module.exports = {
    entry: './path/to/my/entry/file.js'
};

多頁(yè)面配置:

module.exports = {
    entry: {
      'main': "./src/js/index.js",
      'detail': "./src/js/detai.js"
  }
};
  • 輸出output :output 屬性告訴 webpack 在哪里輸出它所創(chuàng)建的 bundles锦茁,以及如何命名這些文件攘轩,默認(rèn)值為 ./dist÷肓基本上撑刺,整個(gè)應(yīng)用程序結(jié)構(gòu),都會(huì)被編譯到指定的輸出路徑的文件夾中握玛。可以通過在配置中指定一個(gè) output 字段甫菠,來配置這些處理過程挠铲。

默認(rèn)值為:

const path = require('path');
module.exports = {
    output: {
        //path需要為絕對(duì)路徑
      path: path.resolve(__dirname, './dist'),
      filename: 'main.js'
    }
};

自定義配置:output 的 filename屬性中,使用[name]來表示entry中的key寂诱;使用[hash]拂苹,會(huì)自動(dòng)在文件名稱后面添加hash值,并直接關(guān)聯(lián)到html模板文件中痰洒。

const path = require('path');
module.exports = {
    entry: {
        'main': "./src/js/index.js",
        'detail': "./src/js/detai.js"
    },
    output: {
        path: path.resolve(__dirname, './dev'),
        filename: '[name]-[hash].js'
    },
};
  • loader:loader 讓 webpack 能夠去處理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)瓢棒。簡(jiǎn)單來說,loader 就是一個(gè)翻譯官丘喻,將瀏覽器不認(rèn)識(shí)的語(yǔ)言脯宿,轉(zhuǎn)化為瀏覽器能解析的語(yǔ)言,loader使用之前需要先安裝泉粉。loader 能夠 import 導(dǎo)入任何類型的模塊(例如 .scss 文件)连霉,這是 webpack 特有的功能,其他打包程序或任務(wù)執(zhí)行器的可能并不支持嗡靡。

webpack.config.js文件:

module.exports = {
 module: {
   rules: [
     {
       test: /\.s[ac]ss$/,
       //當(dāng) use 里有多個(gè)loader時(shí)跺撼,執(zhí)行的順序?yàn)閺挠蚁蜃?       use: [
         // 將 JS 字符串生成為 style 節(jié)點(diǎn),插入html中讨彼,生成內(nèi)聯(lián)樣式
         'style-loader',
         //將 CSS 轉(zhuǎn)化成 CommonJS 模塊歉井,可以直接使用import/require導(dǎo)入
         'css-loader',
         //把.scss文件文件轉(zhuǎn)換為.css文件
         'sass-loader'
       ]
     }
   ]
 }
};

在webpack.config.js文件中,對(duì)一個(gè)單獨(dú)的 module 對(duì)象定義了 rules 屬性哈误,里面包含兩個(gè)必須屬性:test 和 use哩至。這告訴 webpack 編譯器(compiler) 如下信息:當(dāng)編譯器碰到「在 require()/import 語(yǔ)句中被解析為 ‘.sass/.scss’ 的路徑」時(shí)躏嚎,在對(duì)它打包之前,先使用 sass-loader憨募、css-loader紧索、style-loader 轉(zhuǎn)換一下。最終.scss文件會(huì)被轉(zhuǎn)成內(nèi)聯(lián)樣式菜谣,插入html頁(yè)面中珠漂。

  • plugins 插件:loader 被用于轉(zhuǎn)換某些類型的模塊,而插件則可以用于執(zhí)行范圍更廣的任務(wù)尾膊,插件的范圍包括媳危,從打包優(yōu)化和壓縮,一直到重新定義環(huán)境中的變量冈敛。想要使用一個(gè)插件待笑,只需要 require() 它,然后把它添加到 plugins 數(shù)組中抓谴。多數(shù)插件可以通過選項(xiàng)(option)自定義暮蹂,也可以在一個(gè)配置文件中因?yàn)椴煌康亩啻问褂猛粋€(gè)插件,這時(shí)需要通過使用 new 操作符來創(chuàng)建它的一個(gè)實(shí)例癌压。

webpack.config.js文件:

//html-webpack-plugin 將html模板文件和js文件整合到一起
const htmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    plugins: [
        new HtmlWebpackPlugin({
            //模板文件路徑
            template: "./src/views/index.html",
            //自動(dòng)存儲(chǔ)到output 配置的目錄
            filename: 'index.html',
            chunks: ['main']
        })
    ]
};

html-webpack-plugin 插件的作用是將html模板文件和js文件整合到一起仰泻,如果是多頁(yè)面應(yīng)用,則每個(gè)頁(yè)面都需要有對(duì)應(yīng)的new HtmlWebpackPlugin()滩届。webpack在編譯的時(shí)候集侯,會(huì)把所有的 js 合并輸出在一個(gè)js文件,而設(shè)置 chunks 屬性的目的帜消,就是讓當(dāng)前頁(yè)面模板只加載當(dāng)前頁(yè)面所需要的模塊棠枉。上面的寫法表示,在編譯./src/views/index.html 時(shí)泡挺,只需要加載main.js文件辈讶。

四、webpack配置
  • mode 模式
    mode 配置選項(xiàng)娄猫,告知 webpack 使用相應(yīng)模式的內(nèi)置優(yōu)化荞估。有兩個(gè)值:development(開發(fā)模式不會(huì)對(duì)代碼做壓縮、優(yōu)化稚新,方便代碼調(diào)試勘伺,會(huì)將 process.env.NODE_ENV 的值設(shè)為 development)和production(生產(chǎn)模式下會(huì)對(duì)代碼做壓縮、優(yōu)化褂删,會(huì)將 process.env.NODE_ENV 的值設(shè)為 production)飞醉。如果不配置mode,會(huì)有警告信息,但是不影響項(xiàng)目運(yùn)行缅帘。
module.exports = {
    mode:"development",
};
  • devtool
    開發(fā)模式通常配合devtool使用轴术,可以在瀏覽器的控制臺(tái)看到源代碼,而不是解析后的代碼钦无。
module.exports = {
    //代碼調(diào)試逗栽,可以看到源代碼
    devtool: 'inline-source-map',
};
  • webpack-dev-server
    在開發(fā)模式下,新建一個(gè)開發(fā)服務(wù)器失暂,并且當(dāng)代碼更新的時(shí)候自動(dòng)刷新瀏覽器彼宠。可以使用webpack-dev-server插件弟塞。直接使用webpack執(zhí)行凭峡,會(huì)對(duì)文件進(jìn)行打包,并輸出在指定目錄下决记,默認(rèn)為./dev下摧冀。使用webpack-dev-server執(zhí)行,文件會(huì)放在內(nèi)存里系宫,不會(huì)生成整合后的文件索昂,也不會(huì)將文件輸出到指定目錄里。
    在webpack.config.js文件中配置
module.exports = {
    devServer:{
        contentBase:"./dist", //設(shè)置Http服務(wù)器的文件根目錄
        port:8088, //端口
        open:true, //是否打開瀏覽器
        proxy: { //配置代理
          "/api": {
                target: "http://localhost:3000",
                pathRewrite: {"^/api" : ""}
          }
        }
    }
};
  • webpack.config.js
    一個(gè)開發(fā)模式下扩借,完整的webpack.config.js文件內(nèi)容如下:
const path=require("path");
//將html模板和js文件整合在一起
const htmlWebpackPlugin=require("html-webpack-plugin");
//將css樣式提取出來椒惨,使用Link標(biāo)簽導(dǎo)入
const miniCssExtractPlugin=require("mini-css-extract-plugin");
//將靜態(tài)資源打包到輸出目錄中
const copyWebpackPlugin=require("copy-webpack-plugin");

module.exports={
    mode:"development",
    devtool:"inline-source-map",
    entry:"./src/js/index.js",
    output:{
        path:path.resolve(__dirname+"./dev"),
        filename:"[name]-[hash].js"
    },
    devServer:{
        port:8088,
        open:true,
        proxy: { //配置代理
          "/api": {
                target: "http://localhost:3000",
                pathRewrite: {"^/api" : ""}
          }
        }
    },
    plugins:[
        new htmlWebpackPlugin({
            title:"demo title",
            template:"./src/views/index.html",
            filename:"index.html",
            chunks:["main"]
        }),
        new miniCssExtractPlugin({
            filename:"[name]-[hash].css"
        }),
        new copyWebpackPlugin([
            {from:"./src/static",to:"./static"}
        ])
    ],
    module:{
        rules:[
            {
                test:/\.s[ac]ss$/,
                use:[
                    miniCssExtractPlugin.loader,
                    "css-loader",
                    "sass-loader"
                ]
            },        
            {
                test:/\.html$/,
                use:["string-loader"]
            }
        ]
    }
}

package.json文件內(nèi)容如下:

{
  "name": "admin-fe",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "webpack-dev-server --config webpack.config.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "handlebars": "^4.7.3",
    "sme-router": "^0.12.8"
  },
  "devDependencies": {
    "copy-webpack-plugin": "^5.1.1",
    "css-loader": "^3.4.2",
    "html-webpack-plugin": "^4.0.1",
    "mini-css-extract-plugin": "^0.9.0",
    "node-sass": "^4.13.1",
    "sass-loader": "^8.0.2",
    "string-loader": "^0.0.1",
    "style-loader": "^1.1.3",
    "webpack": "^4.42.1",
    "webpack-cli": "^3.3.11",
    "webpack-dev-server": "^3.10.3"
  }
}
五、webpack優(yōu)勢(shì)

與其他的構(gòu)建工具相比往枷,webpack具有如下的一些優(yōu)勢(shì):

  • 對(duì) CommonJS 、 AMD 凄杯、ES6 的語(yǔ)法做了兼容
  • 對(duì) js错洁、css、圖片等資源文件都支持打包
  • 串聯(lián)式模塊加載器以及插件機(jī)制戒突,讓其具有更好的靈活性和擴(kuò)展性屯碴,例如提供對(duì) CoffeeScript、ES6的支持
  • 有獨(dú)立的配置文件 webpack.config.js
  • 可以將代碼切割成不同的 chunk膊存,實(shí)現(xiàn)按需加載导而,降低了初始化時(shí)間
  • 支持 SourceUrls 和 SourceMaps,易于調(diào)試
  • 具有強(qiáng)大的 Plugin 接口隔崎,大多是內(nèi)部插件今艺,使用起來比較靈活
  • webpack 使用異步 IO 并具有多級(jí)緩存,這使得 webpack 很快且在增量編譯上更加快
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末爵卒,一起剝皮案震驚了整個(gè)濱河市虚缎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌钓株,老刑警劉巖实牡,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件陌僵,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡创坞,警方通過查閱死者的電腦和手機(jī)碗短,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來题涨,“玉大人偎谁,你說我怎么就攤上這事⌒埃” “怎么了搭盾?”我有些...
    開封第一講書人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)婉支。 經(jīng)常有香客問我鸯隅,道長(zhǎng),這世上最難降的妖魔是什么向挖? 我笑而不...
    開封第一講書人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任蝌以,我火速辦了婚禮,結(jié)果婚禮上何之,老公的妹妹穿的比我還像新娘跟畅。我一直安慰自己,他們只是感情好溶推,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開白布徊件。 她就那樣靜靜地躺著,像睡著了一般蒜危。 火紅的嫁衣襯著肌膚如雪虱痕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,155評(píng)論 1 299
  • 那天辐赞,我揣著相機(jī)與錄音部翘,去河邊找鬼。 笑死响委,一個(gè)胖子當(dāng)著我的面吹牛新思,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播赘风,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼夹囚,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了邀窃?” 一聲冷哼從身側(cè)響起崔兴,我...
    開封第一講書人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后敲茄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體位谋,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年堰燎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了掏父。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡秆剪,死狀恐怖赊淑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情仅讽,我是刑警寧澤陶缺,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站洁灵,受9級(jí)特大地震影響饱岸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜徽千,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一苫费、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧双抽,春花似錦百框、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至慎菲,卻和暖如春嫁蛇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背钧嘶。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工棠众, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留琳疏,地道東北人有决。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像空盼,于是被迫代替她去往敵國(guó)和親书幕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353