摘要:介紹文件是根據(jù)里面描述的內(nèi)容對一個項(xiàng)目進(jìn)行打包的。配置文件后綴名,除了,還有等等。大部分的對文件的處理的功能都是通過實(shí)現(xiàn)的。下面介紹怎么使用這個功能。
注意:本文描述的配置只適用webpack1.x;由于webpack已經(jīng)推出2.x并有大量更改,特此申明
概述Webpack是一款用戶打包前端模塊的工具。主要是用來打包在瀏覽器端使用的javascript的。同時(shí)也能轉(zhuǎn)換、捆綁、打包其他的靜態(tài)資源,包括css、image、font file、template等。這里就盡量詳細(xì)的來介紹下一些基本功能的使用。
安裝npm install webpack -g運(yùn)行webpack
webpack需要編寫一個config文件,然后根據(jù)這個文件來執(zhí)行需要的打包功能。我們現(xiàn)在來編寫一個最簡單的config。新建一個文件,命名為webpack-config.js。config文件實(shí)際上就是一個Commonjs的模塊。內(nèi)容如下:
var path = require("path"); var buildPath = path.resolve(__dirname,"build"); var nodemodulesPath = path.resolve(__dirname,"node_modules"); var config = { //入口文件配置 entry:path.resolve(__dirname,"src/main.js"), resolve:{ extentions:["","js"]//當(dāng)requrie的模塊找不到時(shí),添加這些后綴 }, //文件導(dǎo)出的配置 output:{ path:buildPath, filename:"app.js" } } module.exports = config;
我的目錄結(jié)構(gòu)是這樣的:
webpack |---index.html |---webpack-config.js |---src |---main.js |---js |---a.js
main.js文件內(nèi)容如下:
var a = require("./js/a"); a(); console.log("hello world"); document.getElementById("container").innerHTML = "hello world
";
a.js文件內(nèi)容如下:
module.exports = function(){ console.log("it is a "); }
然后我們執(zhí)行如下的命令:
webpack --config webpack-config.js --colors
這樣我們就能在目錄里面看到一個新生成的目錄build,目錄結(jié)構(gòu)如下:
webpack |---index.html |---webpack-config.js |---build |---app.js
然后引用app.js就Ok啦。main.js和模塊a.js的內(nèi)容就都打包到app.js中了。這就演示了一個最簡單的把模塊的js打包到一個文件的過程了。
介紹webpack config文件webpack是根據(jù)config里面描述的內(nèi)容對一個項(xiàng)目進(jìn)行打包的。接著我們來解釋下config文件中的節(jié)點(diǎn)分別代表什么意思。一個config文件,基本都是由以下幾個配置項(xiàng)組成的。
entry配置要打包的文件的入口;可以配置多個入口文件,下面會有介紹。
resolve配置文件后綴名(extensions),除了js,還有jsx、coffee等等。
alias配置項(xiàng),可以為常用模塊配置改屬性,可以節(jié)省編譯的搜索時(shí)間。例如:
resolve:{ extensions:[".js",".jsx"], alias:{ "react":path.join(nodeModulesPath,"react/react.js") } }
除了這個功能還可以配置其他有用的功能,由于我還不完全了解,有知道的朋友歡迎指教。
output配置輸出文件的路徑,文件名等。
module(loaders)配置要使用的loader。把資源文件(css、圖片、html等非js模塊)處理成相應(yīng)的js模塊,然后其它的plugins才能對這些資源進(jìn)行下一步處理。比如babel-loader可以把es6的文件轉(zhuǎn)換成es5。
大部分的對文件的處理的功能都是通過loader實(shí)現(xiàn)的。loader可以用來處理在入口文件中require的和其他方式引用進(jìn)來的文件。loader一般是一個獨(dú)立的node模塊,要多帶帶安裝。
loader配置項(xiàng):
test: /.(js|jsx)$/, //注意是正則表達(dá)式,不要加引號,匹配要處理的文件 loader: "eslint-loader", //要使用的loader,"-loader"可以省略 include: [path.resolve(__dirname, "src/app")], //把要處理的目錄包括進(jìn)來 exclude: [nodeModulesPath] //排除不處理的目錄
目前已有的loader列表:https://webpack.github.io/docs/list-of-loaders.html
一個module的例子:
module: { preLoaders: [ { test: /.(js|jsx)$/, loader: "eslint-loader", include: [path.resolve(__dirname, "src/app")], exclude: [nodeModulesPath] }, ], loaders: [ { test: /.(js|jsx)$/, //正則表達(dá)式匹配 .js 和 .jsx 文件 loader: "babel-loader?optional=runtime&stage=0",//對匹配的文件進(jìn)行處理的loader exclude: [nodeModulesPath]//排除node module中的文件 } ] }plugins
顧名思義,就是配置要使用的插件。plugin是比loader功能更強(qiáng)大的插件,能使用更多的wepack api。來看一個使用plugin的例子:
plugins: [ //壓縮打包的文件 new webpack.optimize.UglifyJsPlugin({ compress: { //supresses warnings, usually from module minification warnings: false } }), //允許錯誤不打斷程序 new webpack.NoErrorsPlugin(), //把指定文件夾xia的文件復(fù)制到指定的目錄 new TransferWebpackPlugin([ {from: "www"} ], path.resolve(__dirname,"src")) ]
目前已有的plugins列表:http://webpack.github.io/docs/list-of-plugins.html
如何壓縮輸出的文件plugins: [ //壓縮打包的文件 new webpack.optimize.UglifyJsPlugin({ compress: { //supresses warnings, usually from module minification warnings: false } })]如何copy目錄下的文件到輸出目錄
copy文件需要通過插件"transfer-webpack-plugin"來完成。
安裝:
npm install transfer-webpack-plugin -save
配置:
var TransferWebpackPlugin = require("transfer-webpack-plugin"); //其他節(jié)點(diǎn)省略 plugins: [ //把指定文件夾下的文件復(fù)制到指定的目錄 new TransferWebpackPlugin([ {from: "www"} ], path.resolve(__dirname,"src")) ]打包javascript模塊
支持的js模塊化方案包括:
ES6 模塊
import MyModule from "./MyModule.js";
CommonJS
var MyModule = require("./MyModule.js");
AMD
define(["./MyModule.js"], function (MyModule) { });
上面已經(jīng)演示了打包js模塊,這里不再重復(fù)。ES6的模塊需要配置babel-loader來先把處理一下js文件。
下面展示下打包ES模塊的配置文件:
var webpack = require("webpack"); var path = require("path"); var buildPath = path.resolve(__dirname, "build"); var nodeModulesPath = path.resolve(__dirname, "node_modules"); var TransferWebpackPlugin = require("transfer-webpack-plugin"); var config = { entry: [path.join(__dirname, "src/main.js")], resolve: { extensions: ["", ".js", ".jsx"] //node_modules: ["web_modules", "node_modules"] (Default Settings) }, output: { path: buildPath, filename: "app.js" }, plugins: [ new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }), new webpack.NoErrorsPlugin(), new TransferWebpackPlugin([ {from: "www"} ], path.resolve(__dirname,"src")) ], module: { preLoaders: [ { test: /.(js|jsx)$/, loader: "eslint-loader", include: [path.resolve(__dirname, "src/app")], exclude: [nodeModulesPath] }, ], loaders: [ { test: /.js$/, //注意是正則表達(dá)式,不要加引號 loader: "babel-loader?optional=runtime&stage=0",//babel模塊相關(guān)的功能請自查,這里不做介紹 exclude: [nodeModulesPath] } ] }, //Eslint config eslint: { configFile: ".eslintrc" //Rules for eslint }, }; module.exports = config;打包靜態(tài)資源 css/sass/less
安裝css-loader和style-loader
npm install css-loader --save -dev npm install style-loader --save -dev
config配置:
var config = { entry:path.resolve(__dirname,"src/main.js"), resolve:{ extentions:["","js"] }, output:{ path:buildPath, filename:"app.js" }, module:{ loaders:[{ test:/.css$/, loader:"style!css",//sass配置:style!css!sass 執(zhí)行順序:左<--右 exclude:nodemodulesPath }] } }
style-loader會把css文件嵌入到html的style標(biāo)簽里,css-loader會把css按字符串導(dǎo)出,這兩個基本都是組合使用的。打包完成的文件,引用執(zhí)行后,會發(fā)現(xiàn)css的內(nèi)容都插入到了head里的一個style標(biāo)簽里。
如果是sass或less配置方式與上面類似。
可以通過url-loader把較小的圖片轉(zhuǎn)換成base64的字符串內(nèi)嵌在生成的文件里。
安裝:
npm install url-loader --save -dev
config配置:
var config = { entry:path.resolve(__dirname,"src/main.js"), resolve:{ extentions:["","js"] }, output:{ path:buildPath, filename:"app.js" }, module:{ loaders:[{ test:/.css$/, loader:"style!css",// exclude:nodemodulesPath }, { test:/.png$/,loader:"url-loader?limit=10000"}//限制大小小于10k的 ] } }
css文件內(nèi)容:
#container{ color: #f00; background:url(images/logo-201305.png); /*生成完圖片會被處理成base64的字符串 注意:不要寫"/images/logo-201305.png",否則圖片不被處理*/ }iconfont
內(nèi)嵌iconfont的使用方法其實(shí)和上述處理png圖片的方法一致。通過url-loader來處理。
config配置:
var config = { entry:path.resolve(__dirname,"src/main.js"), resolve:{ extentions:["","js"] }, output:{ path:buildPath, filename:"app.js" }, module:{ loaders:[{ test:/.css$/, loader:"style!css",// exclude:nodemodulesPath }, { test:/.(png|woff|svg|ttf|eot)$/,loader:"url-loader?limit=10000"}//限制大小小于10k的 ] } }
css文件內(nèi)容:
@font-face {font-family: "iconfont"; src: url("fonts/iconfont.eot"); /* IE9*/ src: url("fonts/iconfont.eot?#iefix") format("embedded-opentype"), /* IE6-IE8 */ url("fonts/iconfont.woff") format("woff"), /* chrome、firefox */ url("fonts/iconfont.ttf") format("truetype"), /* chrome、firefox、opera、Safari, Android, iOS 4.2+*/ url("fonts/iconfont.svg#iconfont") format("svg"); /* iOS 4.1- */ }
執(zhí)行打包后會把字體文件都轉(zhuǎn)換成base64字符串內(nèi)容到文件里.
這里有個頭疼的問題,就是每個瀏覽器支持的字體格式不一樣,由于把全部格式的字體打包進(jìn)去,造成不必要的資源浪費(fèi)。
我以打包handlebars的模塊為例,來演示下打包模塊的過程。有的模板對應(yīng)的loader,有可能沒有現(xiàn)成的,恐怕要自己實(shí)現(xiàn)loader。
先安裝必須的node模塊
npm install handlebars-loader --save -dev npm install handlebars -save//是必須的
config配置:
var config = { entry:path.resolve(__dirname,"src/main.js"), resolve:{ extentions:["","js"] }, output:{ path:buildPath, filename:"app.js" }, module:{ loaders:[ { test: /.html$/, loader: "handlebars-loader" } ] } }
新建一個模板文件tb.html,目錄結(jié)構(gòu):
webpack |---index.html |---webpack-config.js |---src |---template | |---tb.html |---main.js
main.js中調(diào)用模塊的代碼如下:
var template = require("./template/tp.html"); var data={say_hello:"it is handlebars"}; var html = template(data); document.getElementById("tmpl_container").innerHTML = html;公用的模塊分開打包
這需要通過插件“CommonsChunkPlugin”來實(shí)現(xiàn)。這個插件不需要安裝,因?yàn)閣ebpack已經(jīng)把他包含進(jìn)去了。
接著我們來看配置文件:
var config = { entry:{app:path.resolve(__dirname,"src/main.js"), vendor: ["./src/js/common"]},//【1】注意這里 resolve:{ extentions:["","js"] }, output:{ path:buildPath, filename:"app.js" }, module:{ loaders:[{ test:/.css$/, loader:"style!css", exclude:nodemodulesPath } ] }, plugins:[ new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }), //【2】注意這里 這兩個地方市用來配置common.js模塊多帶帶打包的 new webpack.optimize.CommonsChunkPlugin({ name: "vendor",//和上面配置的入口對應(yīng) filename: "vendor.js"http://導(dǎo)出的文件的名稱 }) ] }
目錄結(jié)構(gòu)現(xiàn)在是這樣的:
webpack |---index.html |---webpack-config.js |---src |---main.js |---js |---a.js //a里面require了common |---common.js
執(zhí)行webpack會生成app.js和common.js兩個文件.
code split(模塊分離,按需加載)有些場景,我們可能希望模塊在需要的時(shí)候再加載,而不是一股腦兒打包到一起。從而加速首屏的加載速度。舉個例子,在做單頁應(yīng)用的時(shí)候,每個場景對應(yīng)一個模塊。如果場景很多,把模塊打包到一起,最后的bundle文件必然很臃腫,加載很慢。那么只要在每個場景需要展示的時(shí)候,再加載對應(yīng)的js模塊。就可以優(yōu)化這個問題了。webpack支持模塊按需加載,這個功能叫code split。下面介紹怎么使用這個功能。
目錄結(jié)構(gòu):
webpack |---index.html |---webpack-config.js |---src |---main.js |---js |---codeSplit.js
codeSplit.js:
//就是普通的模塊 沒什么特殊的 console.log("code split"); module.exports = { name:"cplll" }
main.js:
var cp = function(resolve){ require.ensure(["./js/codeSplit.js"],function(){//注意這里哦,就是用require.ensure來按需加載的,這是webpack特有的 resolve(require("./js/codeSplit.js"));//加載好 require模塊 }); } var getModule = function(){ return new Promise((resolve,reject)=>{ cp(resolve); }); } getModule().then((cl)=>{ console.log(cl.name); });
config配置:
//...省略 var buildPath = path.resolve(__dirname,"build"); var config = { entry:{ m1:path.resolve(__dirname,"src/main.js") },//注意在這里添加文件的入口 resolve:{ extentions:["","js"] }, output:{ path:buildPath, filename:"app.js", publicPath:"build/" //注意這里哦,分離出來的模塊會按這個路徑來加載 } }
執(zhí)行命令:
webpack --config webpack-config.js --colors
生成結(jié)果:
webpack |---index.html |---webpack-config.js |---build //生成結(jié)果 | |---app.js | |---1.app.js |---src |---main.js |---js |---codeSplit.js
頁面里引用
打開頁面就是發(fā)現(xiàn),app.js和1.app.js(在cp函數(shù)調(diào)用的時(shí)候加載)分開加載了。
最后需要特別注意,配置output里的publicPath。這里容易有坑。因?yàn)椴慌渲眉虞d路徑是這樣的:
http://localhost:9527/1.app.js
配置以后(publicPath:"build/"):
http://localhost:9527/build/1.app.js多個入口
config配置:
var config = { entry:{ m1:path.resolve(__dirname,"src/main.js"), m2:path.resolve(__dirname,"src/main1.js") },//注意在這里添加文件的入口 resolve:{ extentions:["","js"] }, output:{ path:buildPath, filename:"[name].js"http://注意這里使用了name變量 } }webpack-dev-server
在開發(fā)的過程中個,我們肯定不希望,每次修改完都手動執(zhí)行webpack命令來調(diào)試程序。所以我們可以用webpack-dev-server這個模塊來取代煩人的執(zhí)行命令。它會監(jiān)聽文件,在文件修改后,自動編譯、刷新瀏覽器的頁面。另外,編譯的結(jié)果是保存在內(nèi)存中的,而不是實(shí)體的文件,所以是看不到的,因?yàn)檫@樣會編譯的更快。它就想到與一個輕量的express服務(wù)器。
安裝:
npm install webpack-dev-server --save -dev
config配置:
var config = { entry:path.resolve(__dirname,"src/main.js"), resolve:{ extentions:["","js"] }, //Server Configuration options devServer:{ contentBase: "", //靜態(tài)資源的目錄 相對路徑,相對于當(dāng)前路徑 默認(rèn)為當(dāng)前config所在的目錄 devtool: "eval", hot: true, //自動刷新 inline: true, port: 3005 }, devtool: "eval", output:{ path:buildPath, filename:"app.js" }, plugins: [ new webpack.HotModuleReplacementPlugin(),//開啟熱替換插件 new webpack.NoErrorsPlugin() ] }
我的目錄結(jié)構(gòu):
webpack |---index.html |---webpack-config.js//我把靜態(tài)資源目錄配置在了這里 |---src |---main.js |---js |---a.js |---common.js
執(zhí)行命令:
webpack-dev-server --config webpack-dev-config.js --inline --colors
默認(rèn)訪問地址:
http://localhost:3000/index.html(根據(jù)配置會不一樣)
有一點(diǎn)需要聲明,在index.html(引用導(dǎo)出結(jié)果的html文件)里直接引用“app.js”,不要加父級目錄,因?yàn)榇藭r(shí)app.js在內(nèi)存里與output配置的目錄無關(guān):
詳細(xì)文檔在這里查看:http://webpack.github.io/docs/webpack-dev-server.html
Hot Module Replacement熱替換是指在應(yīng)用運(yùn)行時(shí)候替換、添加、移除某個模塊而不需要全部模塊重新編譯、整個頁面重新加載。在web應(yīng)用變的越來越復(fù)雜的今天,webpack的編譯速度會越來越慢。使用熱替換能大大提高webpack的編譯速度,提升開發(fā)效率。下面介紹如何基于webpack-dev-server配置熱替換。
config配置:
var config = { entry:[ "webpack/hot/dev-server",//注意點(diǎn)1:熱替換配置點(diǎn)1 path.resolve(__dirname,"src/main1.js") ], // entry:{m1:path.resolve(__dirname,"src/main.js"), // m2:path.resolve(__dirname,"src/main1.js")}, resolve:{ extentions:["","js"] }, // target: "node", //Server Configuration options devServer:{ contentBase: "", //Relative directory for base of server devtool: "eval", hot: true, //注意點(diǎn)2:熱替換配置點(diǎn)2 inline: true, port: 3005 //Port Number }, devtool: "eval", output:{ path:buildPath, filename:"app.js" }, plugins: [ //Enables Hot Modules Replacement new webpack.HotModuleReplacementPlugin(),//注意點(diǎn)3:熱替換配置點(diǎn)3 //Allows error warnings but does not stop compiling. Will remove when eslint is added new webpack.NoErrorsPlugin() ], }
配置文件里添加3個配置點(diǎn)
entry 節(jié)點(diǎn)里添加 "webpack/hot/dev-server"
devServer節(jié)點(diǎn)里添加 hot: true
plugins 節(jié)點(diǎn)里 new webpack.HotModuleReplacementPlugin()
這樣配置文件就配置好了。接下來在代碼文件里添加熱替換要監(jiān)聽的模塊。代碼如下:
var h1 = require("./hot1"); if(module.hot){//判斷是否開啟了熱替換 module.hot.accept("./hot1",function(){//在hot1模塊更新時(shí),執(zhí)行替換 h1 = require("./hot1"); }); }
更多信息參考:webpack-dev-server和熱替換介紹
如何區(qū)分開發(fā)及生產(chǎn)環(huán)境在webpack.config.js使用process.env.NODE_ENV進(jìn)行判斷
在package.json里面的script設(shè)置環(huán)境變量,注意mac與windows的設(shè)置方式不一樣
"scripts": { "publish-mac": "export NODE_ENV=prod&&webpack -p --progress --colors", "publish-win": "set NODE_ENV=prod&&webpack -p --progress --colors", "dev-mac": "export NODE_ENV=dev&&webpack-dev-server", "dev-win": "set NODE_ENV=dev&&webpack-dev-server }
config配置:
//其他代碼省略... var NODE_ENV = process.env.NODE_ENV; var config = { //入口文件配置 entry: path.resolve(__dirname, "src/main.js"), resolve: { extentions: ["", "js"]//當(dāng)requrie的模塊找不到時(shí),添加這些后綴 }, devtool: "eval", //文件導(dǎo)出的配置 output: { path: buildPath, filename: "app.js" }, module: { loaders: [ { test: /.html$/, loader: "tmodjs",//對匹配的文件進(jìn)行處理的loader exclude: [nodemodulesPath]//排除node module中的文件 } ] } } if(NODE_ENV === "prod"){//判斷是生產(chǎn)環(huán)境執(zhí)行生產(chǎn)配置 delete config.devtool; config.plugins = [ //壓縮打包的文件 new webpack.optimize.UglifyJsPlugin({ compress: { //supresses warnings, usually from module minification warnings: false } })]; }
之后dev環(huán)境執(zhí)行命令:npm run dev-win
生產(chǎn)環(huán)境執(zhí)行命令:npm run publish-win
代碼熱替換, HotModuleReplacementPlugin
將css成生文件,而非內(nèi)聯(lián),ExtractTextPlugin
報(bào)錯但不退出webpack進(jìn)程,NoErrorsPlugin
多個 html共用一個js文件(chunk),可用CommonsChunkPlugin
清理文件夾,Clean
調(diào)用模塊的別名ProvidePlugin,例如想在js中用$,如果通過webpack加載,需要將$與jQuery對應(yīng)起來
參考文章* webpack使用優(yōu)化
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/78348.html
摘要:初始化項(xiàng)目官方文檔項(xiàng)目地址項(xiàng)目搭建簡單記錄一下命令,網(wǎng)上有很多文章不多做介紹。希望可以提供一個基礎(chǔ)的架構(gòu)。 初始化項(xiàng)目 webpack官方文檔:https://www.webpackjs.com/con...github項(xiàng)目地址:https://github.com/Zhanghongw... 項(xiàng)目搭建簡單記錄一下命令,網(wǎng)上有很多文章不多做介紹。希望可以提供一個基礎(chǔ)的架構(gòu)。 持續(xù)更新....
摘要:名稱后自動自動補(bǔ)全的功能將被移除在配置時(shí),官方不再允許省略擴(kuò)展名,的配置寫法上將逐步趨于嚴(yán)謹(jǐn)。使用自定義參數(shù)作為配置項(xiàng)傳入方式將做調(diào)整如果你隨意將自定義參數(shù)通過傳入到配置項(xiàng)中,如你會發(fā)現(xiàn)這將不會被允許,的執(zhí)行將會遵循更為嚴(yán)格的標(biāo)準(zhǔn)。 歷時(shí)多日,webpack2.2正式版終于趕在年前發(fā)布了,此次更新相對于1.X版本有了諸多的升級優(yōu)化改進(jìn),筆者也在第一時(shí)間查閱了官方的文檔,整理和翻譯了由w...
摘要:名稱后自動自動補(bǔ)全的功能將被移除在配置時(shí),官方不再允許省略擴(kuò)展名,的配置寫法上將逐步趨于嚴(yán)謹(jǐn)。使用自定義參數(shù)作為配置項(xiàng)傳入方式將做調(diào)整如果你隨意將自定義參數(shù)通過傳入到配置項(xiàng)中,如你會發(fā)現(xiàn)這將不會被允許,的執(zhí)行將會遵循更為嚴(yán)格的標(biāo)準(zhǔn)。 從 webpack v1 遷移到 webpack v2 新特性 歡迎小伙伴們?yōu)? 前端導(dǎo)航平臺 點(diǎn)star github倉庫: https://githu...
摘要:從再到目前當(dāng)紅明星,前端模塊打包技術(shù)日新月異,在今年月份和月份左右接連更新了和版本為了減少冗余模塊,縮減文件大小,中也加入了關(guān)于的特征,可以查看知乎如何評價(jià)新引入的代碼優(yōu)化技術(shù)的討論。 從Grunt->gulp->webpack,再到目前當(dāng)紅明星rollup,前端模塊打包技術(shù)日新月異,webpack在今年1月份和6月份左右接連更新了v2和v3版本,為了減少冗余模塊,縮減bundle文件...
閱讀 3903·2021-11-22 13:54
閱讀 2675·2021-09-30 09:48
閱讀 2361·2021-09-28 09:36
閱讀 3113·2021-09-22 15:26
閱讀 1343·2019-08-30 15:55
閱讀 2509·2019-08-30 15:54
閱讀 1426·2019-08-30 14:17
閱讀 2341·2019-08-28 18:25