摘要:通過(guò)中的通過(guò)選項(xiàng)使用方法通過(guò)通過(guò)我發(fā)現(xiàn)通過(guò)設(shè)置的配置項(xiàng)有時(shí)不起作用。當(dāng)代碼發(fā)生變化時(shí),以下種方式都會(huì)重新打包,但是不會(huì)重載頁(yè)面會(huì)重載整個(gè)頁(yè)面若失敗則加載整個(gè)頁(yè)面指出了打包入口文件,支持字符串?dāng)?shù)組和對(duì)象三種形式。
【注】本文原發(fā)自此處,轉(zhuǎn)載請(qǐng)注明出處。
本文譯自【W(wǎng)ebpack-The Confusing Parts】原文
本文已同步發(fā)表在我的博客
前言webpack是當(dāng)前最受歡迎的模塊管理器(module bundler),對(duì)于使用React開發(fā)的項(xiàng)目來(lái)說(shuō)堪稱神器。當(dāng)然,對(duì)于使用其他框架,比如Angular或者Backbone等的開發(fā)者來(lái)說(shuō),webpack也是種很好的工具。
第一次配置webpack.config.js時(shí),有很多地方使我很困惑。在使用了webpack一段時(shí)間后,我認(rèn)識(shí)到正是這些地方讓webpack如此強(qiáng)大和迷人。
webpack核心理念一切都是模塊?!?在webpack中,不僅js文件可以作為一個(gè)模塊,其他文件(css,images,html)都可以作為模塊。這就是說(shuō),你可以在其他文件中加載這些模塊,require("myJSfile.js"),或者require("myCSSfile.css")。這意味著我們將任意文件拆分成便于管理的小文件,然后通過(guò)在其他文件中加載這些小文件來(lái)達(dá)到重復(fù)利用的目的。
按需加載(Load only "what" you need and "when" you need)—— 一般情況下打包工具會(huì)將我們所有的模塊打包生成一個(gè)最終的文件bundle.js。但是在實(shí)際應(yīng)用中,bundle.js通常會(huì)很大(10M~15M),需要很長(zhǎng)時(shí)間才能加載完成。webpack提供了多種code splitting的方法,會(huì)生成過(guò)個(gè)打包后的文件,且支持按需加載。這樣我們只有在需要用到某個(gè)模塊的時(shí)候才會(huì)異步加載該模塊。
現(xiàn)在我們來(lái)看下這些令人困惑的部分。
開發(fā)環(huán)境和生產(chǎn)環(huán)境(Development Vs Production)首先要明確的一點(diǎn)是,webpack有很多特性,有些只在開發(fā)環(huán)境使用,還有些只在生產(chǎn)環(huán)境使用,當(dāng)然還有在生產(chǎn)環(huán)境和開發(fā)環(huán)境都可以使用的。如下圖所示:
所以通常我們會(huì)有兩個(gè)config文件,以針對(duì)開發(fā)環(huán)境和生產(chǎn)環(huán)境作不同配置。
在package.json做如下配置:
"scripts": { //npm run build to build production bundles "build": "webpack --config webpack.config.prod.js", //npm run dev to generate development bundles and run dev. server "dev": "webpack-dev-server" }webpack CLI Vs webpack-dev-server
需要知道webpack提供了兩個(gè)接口
webpack命令行工具(webpack CLI tool) —— 默認(rèn)使用這種方式,無(wú)需多帶帶安裝,被集成在webpack中。
webpack-dev-server —— node.js 服務(wù)器,需要多帶帶安裝
Webpack CLI (適用于生產(chǎn)環(huán)境構(gòu)建)可以通過(guò)命令行添加參數(shù),也可以通過(guò)配置文件(默認(rèn)為webpack.config.js),webpack打包時(shí)會(huì)讀取這些配置。
最初學(xué)習(xí)webpack時(shí)你可能用的就是命令行方式,之后大部分使用命令行的場(chǎng)景為生產(chǎn)環(huán)境打包。
使用方法
方法 1: //全局安裝 npm install webpack --g //在命令行使用 $ webpack //<--Generates bundle using webpack.config.js 方法 2 : //本地安裝并保存在package.json中 npm install webpack --save //在scripts中添加 "scripts": { "build": "webpack --config webpack.config.prod.js -p", ... } //按以下方式運(yùn)行 "npm run build"webpack-dev-server(適用于開發(fā)環(huán)境構(gòu)建)
webpack-dev-server是一個(gè)基于Express的node服務(wù)器,默認(rèn)使用8080端口。這個(gè)方式的優(yōu)點(diǎn)是它提供了瀏覽器熱加載(Hot Module Replacement)。
使用方法
方法一: //全局安裝 npm install webpack-dev-server -g //在命令行使用 $ webpack-dev-server --inline --hot 方法二: //添加到package.json中 "script": { "start": "webpack-dev-server --inline --hot", ... } //在命令行使用 $ npm start 在瀏覽器中打開 http://localhost:8080/webpack和webpack-dev-server選項(xiàng)
需要注意的一點(diǎn)是,像inline和hot這些選項(xiàng),只有webpack-dev-server有;而另一些比如hide-modules是多帶帶為webpack命令行方式提供的選項(xiàng)。
webpack-dev-server參數(shù)為webpack-dev-server提供參數(shù)有兩種方式。
通過(guò)webpack.config.js中的devServer
通過(guò)CLI選項(xiàng)
使用方法
//通過(guò)CLI $ webpack-dev-server --hot --inline //通過(guò)webpack.config.js devServer: { inline: true, hot: true }
我發(fā)現(xiàn)通過(guò)devServer設(shè)置的配置項(xiàng)(hot: true, inline: true)有時(shí)不起作用。所以我更喜歡使用CLI的方式,在package.json中添加如下代碼:
package.json { "script": { "start": "webpack-dev-server --hot --inline" } }
注意不要同時(shí)設(shè)置devServer中hot: true和CLI中--hot"hot" Vs "inline"
inline模式會(huì)觸發(fā)頁(yè)面的動(dòng)態(tài)重載(live reloading);hot模式會(huì)觸發(fā)頁(yè)面的熱加載(hot Module Replacement),這種模式只重載頁(yè)面中變化了的部分。如果同時(shí)設(shè)置了inline和hot,webpack-dev-server會(huì)先嘗試HMR,如果HMR失敗了,則重載整個(gè)頁(yè)面。
//當(dāng)代碼發(fā)生變化時(shí),以下3種方式都會(huì)重新打包,但是: //1. 不會(huì)重載頁(yè)面 $ webpack-dev-server //2. 會(huì)重載整個(gè)頁(yè)面 $ webpack-dev-server --inline //3. HMR, 若失敗則加載整個(gè)頁(yè)面 $ webpack-dev-server --inline --hotentry(String Vs Array Vs Object)
entry指出了打包入口文件,支持字符串,數(shù)組和對(duì)象三種形式。這三種形式有何區(qū)別呢?
如果為單一入口文件,也就是說(shuō)入口文件只有一個(gè),那這三種方式會(huì)得到相同的結(jié)果。entry — Array
若有多個(gè)入口文件,且彼此獨(dú)立,那么可以使用數(shù)組方式。比如入口文件為a.js,b.js,使用數(shù)組方式會(huì)將b.js的內(nèi)容追加到bundle.js的內(nèi)容后。
一個(gè)很常見的場(chǎng)景就是在html文件加入統(tǒng)計(jì)代碼,比如googleAnalytics.js,就可以用數(shù)組的方式告知webpack將其打包到bundle.js末尾,如下:
這種方式主要針對(duì)多頁(yè)面應(yīng)用(指包含多個(gè)html文件)。這種方式可以使webpack根據(jù)這個(gè)對(duì)象一次就打包出多個(gè)文件。
如下這種配置可以打包出兩個(gè)js文件:indexEntry.js和profileEntry.js,可以分別在index.html和profile.html中引入。
{ entry: { "indexEntry": "./public/src/index.js", "profileEntry": "./public/src/profile.js" }, output: { path: "/dist", filename: "[name].js" //indexEntry.js & profileEntry.js } }
使用方法
//profile.html //index.html
注: output中name對(duì)應(yīng)的是entry中的屬性名。
entry — 結(jié)合使用array和object可以在object內(nèi)部再使用array方式。比如如下配置:
{ entry: { "vendor": ["jquery", "analytics.js", "optimizely.js"], "index": "./public/src/index.js", "profile": "./public/src/profile.js" }, output: { path: "/dist", filename: "[name].js" //vendor.js, index.js & profile.js } }output — path和publicPath
output設(shè)定了打包生成文件的路徑。它有兩個(gè)屬性path和publicPath。
path告知webpack將打包生成后的文件存儲(chǔ)于什么路徑,比如我們希望將文件打包到dist文件夾下,只需設(shè)置path為/dist即可;publicPath用于在生產(chǎn)環(huán)境打包時(shí)更新文件(包括css、html)中的url。
如下配置:
//開發(fā)環(huán)境config entry: __dirname + "/app/main.js", output: { path: __dirname + "/public", //開發(fā)環(huán)境中不需要使用publicPath, 除非你的靜態(tài)資源比如圖片等沒(méi)有存儲(chǔ)在本地開發(fā)環(huán)境。 //publicPath: "http://mycdn.com", filename: "bundle.js" } //生產(chǎn)環(huán)境config entry: __dirname + "/app/main.js", output: { path: __dirname + "/public", //publicPath: 一些插件(url-loader, file-loader, HtmlWebpackPlugin等) //在生成圖片,樣式表等的url路徑時(shí)會(huì)用到該配置 //比如: //.image { // background-image: url("./test/png"); //} //按如下配置打包后會(huì)變成: //.image { // background-image: url("http://mycdn.com/test.png"); //} publicPath: "http://mycdn.com/", filename: "bundle.js" }
舉個(gè)例子,在你的css文件中,用到了./test.png這個(gè)url去加載本地的圖片。但是在生產(chǎn)環(huán)境中,這張圖片test.png會(huì)存儲(chǔ)在cdn服務(wù)器上。這樣如果還是用./test.png就會(huì)訪問(wèn)不到該圖片,必須把文件中所有的url手動(dòng)改成cdn的路徑才能在生產(chǎn)環(huán)境使用。
webpack為我們提供的publicPath這個(gè)屬性使我們可以很方便地處理這類問(wèn)題。只需要將publicPath設(shè)置為生產(chǎn)環(huán)境的路徑,這些識(shí)別publicPath的插件,比如url-loader,就會(huì)自動(dòng)為我們處理好url。如下圖所示:
//開發(fā)環(huán)境,server和image都在本地 .image { background-image: url("./test.png"); } //生產(chǎn)環(huán)境, server在HeroKu服務(wù)器上,而image在cdn上 .image { background-image: url("https://someCDN/test.png"); }
(譯者注: publicPath還用于指定在使用webpack-dev-server時(shí),如何訪問(wèn)其暫存于內(nèi)存中的打包后的文件。)
加載器和鏈?zhǔn)郊虞d器(Loaders And Chaining Loaders)加載器是一些node模塊,可以加載(load)或者引入(import)各種類型的文件使其轉(zhuǎn)化成瀏覽器支持的文件格式,包括js,css等等。
比如:可以使用babel-loader將使用ES6寫的js文件轉(zhuǎn)換為瀏覽器支持的ES5格式。如下:
module { loaders: [ { test: /.js$/, //檢測(cè)js文件,如果是,則對(duì)其使用loader處理 exclude: /node_modules/, //不對(duì)node_modules下文件處理 loader: "babel" //使用babel (對(duì)babel-loader的簡(jiǎn)寫) } ] }鏈?zhǔn)郊虞d(從右至左)
對(duì)同一種類型的文件可以鏈?zhǔn)竭\(yùn)用多個(gè)加載器。鏈?zhǔn)秸{(diào)用為從右向左,通過(guò)!分割加載器。
舉例:我們有一個(gè)css文件myCSSFile.css,我們想將這個(gè)文件中的內(nèi)容轉(zhuǎn)換成的形式插入到我們的html頁(yè)面中??梢允褂脙蓚€(gè)加載器css-loader和style-loader來(lái)達(dá)成以上目的:
modules: { loaders: [ { test: /.css$/, loader: "style!css" //style-loader!css-loader的簡(jiǎn)寫 } ] }
如下展示了其原理:
1、webpack查找模塊中依賴的css文件。也就是說(shuō),webpack會(huì)檢查js文件中是否引用了myCSSFile.css。如果找到了依賴,webpack會(huì)先用css-loader對(duì)其進(jìn)行處理。
2、css-loader會(huì)加載所有的css和這個(gè)css的依賴(比如@import otherCSS),并將css的內(nèi)容處理為JSON數(shù)據(jù)格式。然后將結(jié)果傳給style-loader進(jìn)行處理。
3、style-loader會(huì)對(duì)接收到的json數(shù)據(jù)進(jìn)行處理,并將其處理為style標(biāo)簽——,然后插入到html頁(yè)面中。
可以向loaders傳遞各種參數(shù)進(jìn)行配置。
在以下這個(gè)例子中,我們對(duì)url-loader進(jìn)行了配置:小于1024字節(jié)的圖片將會(huì)被轉(zhuǎn)為為base64格式,而大于1024字節(jié)的圖片還是使用圖片url。有兩種方式進(jìn)行配置:
//方式1 使用"?" { test: /.png$/, loader: "url-loader?limit=1024" } //方式2 使用"query"屬性 { test: /.png$/, loader: "url-loader", query: {limit: 1024} }.babelrc文件
使用babel-loader的話,需要配置presets才能正確轉(zhuǎn)化,包括將es6轉(zhuǎn)換為es5,將JSX轉(zhuǎn)為js??梢酝ㄟ^(guò)如下方式設(shè)置參數(shù)
module: { loaders: [ { test: /.jsx?$/, exclude: /(node_modules|bower_components)/, loader: "babel", query: { presets: ["react", "es2015"] } } ] }
但是在很多項(xiàng)目中babel的配置可能會(huì)比較大,所以可以多帶帶在babel的配置文件.babelrc中配置。如果有.babelrc,babel-loader會(huì)自動(dòng)加載該文件。
如下:
//webpack.config.js module: { loaders: [ { test: /.jsx?$/, exclude: /(node_modules|bower_components)/, loader: "babel" } ] } //.babelrc { "presets": ["react", "es2015"] }插件(Plugins)
插件是一些node模塊,可以對(duì)生成的打包文件進(jìn)行處理。
比如,uglifyJSPlugin插件可以對(duì)打包后得到的bundle.js進(jìn)行壓縮處理,減小文件體積。
extract-text-webpack-plugin運(yùn)用了css-loader和style-loader將所有的css統(tǒng)一處理并根據(jù)結(jié)果生成一個(gè)多帶帶的css文件(style.css),將文件鏈接插入到html文件中。
//webpack.config.js //獲取所有的css文件,并將其內(nèi)容整合,生成一個(gè)多帶帶的css文件"style.css" var ETP = require("extract-text-webpack-plugin"); module: { loaders: [ { test: /.css$/, loader: ETP.extract("style-loader", "css-loader") } ] }, plugins: [ new ExtractTextPlugin("style.css") ]
注:
如果你只是想使用內(nèi)聯(lián)css樣式,在html頁(yè)面中加入style標(biāo)簽,可以只用css和style加載器。如下:
module: { loaders: [ { test: /.css$/, loader: "style!css" } ] }加載器和插件(Loaders Vs Plugins)
可以看到,加載器作用于多帶帶的文件,在bundle生成之前完成;
插件作用于bundle或chunk,通常是在bundle生成過(guò)程的最后進(jìn)行。一些插件比如commonsChunksPlugins甚至?xí)绊?b>bundle如何生成。(譯者注:該插件用于提取出各個(gè)模塊中引用的相同模塊,下篇文章code splitting中會(huì)詳細(xì)說(shuō)明)
很多webpack配置文件中都包含一個(gè)resolve extensions的屬性,其中包含一個(gè)空字符串。這個(gè)空字符串就是用于正確加載不含后綴的文件的。比如:require("./myJSFile") 或 import myJSFile from "./myJSFile" 。
{ resolve: { extensions: ["", ".js", ".jsx"] } }
注: 翻譯水平有限,如有問(wèn)題還希望大家能不吝賜教,希望和大家共同進(jìn)步。
(本文完)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/80831.html
摘要:前端日?qǐng)?bào)精選浮點(diǎn)數(shù)精度之謎前端面試必備基本排序算法從賀老微博引出的遍歷器加速那些奧秘進(jìn)階之深入理解數(shù)據(jù)雙向綁定全棧天中文深入理解筆記用模塊封裝代碼前端架構(gòu)經(jīng)驗(yàn)分享周二放送自制知乎專欄譯在大型應(yīng)用中使用的五個(gè)技巧掘金開發(fā)指南眾成 2017-08-02 前端日?qǐng)?bào) 精選 JavaScript 浮點(diǎn)數(shù)精度之謎前端面試必備——基本排序算法從賀老微博引出的遍歷器(Iterators)加速那些奧秘J...
摘要:處理文件的擴(kuò)展名很多的配置文件都有一個(gè)屬性,然后就像下面代碼所示有一個(gè)空字符串的值??兆址诖耸菫榱艘恍┰谖募r(shí)不帶文件擴(kuò)展名的表達(dá)式,如或者譯者注實(shí)際就是自動(dòng)添加后綴,默認(rèn)是當(dāng)成文件來(lái)查找路徑就這么多。 原文 Webpack—The Confusing Partsissue討論 Webpack是目前基于React和Redux開發(fā)的應(yīng)用的主要打包工具。我想使用Angular 2或其他...
摘要:索引失效,使用全表掃描。但可以通過(guò)翻轉(zhuǎn)函數(shù)前模糊查詢建立翻轉(zhuǎn)函數(shù)索引走翻轉(zhuǎn)函數(shù)索引,不走全表掃描。有效降低消耗值,值,值這三個(gè)指標(biāo),尤其是值的降低。 like %keyword 索引失效,使用全表掃描。但可以通過(guò)翻轉(zhuǎn)函數(shù)+like前模糊查詢+建立翻轉(zhuǎn)函數(shù)索引=走翻轉(zhuǎn)函數(shù)索引,不走全表掃描。 like keyword% 索引有效。 like %keyword% 索引失效,也...
閱讀 1074·2023-04-26 03:03
閱讀 2431·2021-10-12 10:12
閱讀 1382·2021-09-24 09:48
閱讀 1829·2021-09-22 15:25
閱讀 3595·2021-09-22 15:15
閱讀 1086·2019-08-29 16:21
閱讀 1217·2019-08-28 18:00
閱讀 3574·2019-08-26 13:44