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