2017/12/18/更新
已經有一段時間沒有更新webpack了,從如今的角度看,文章有一部份內容也是不夠成熟,後續仍是會繼續梳理更新的。css
網上關於webpack的教程已經數不勝數了,也無心再從新寫一篇複製文。可是實際操做過程當中,發現各類教程版本都不一致,有的教程已通過時了,有的教程模糊不清,所以仍是遇到了各類問題,所以特將自身實際操做過程當中遇到的問題記錄下來,並附上相應的示例demo,也但願能給他人帶來幫助!html
本文主要是記錄的一些遇到的問題以及提供了示例,若是想要看入門教程仍是去官網上或者參考參考資源中的連接。node
問題記錄較多,想要直接看示例Demo的請拉到最下方。webpack
另外,此文會持續更新。git
README
說明:項目的package.json中,只要帶有註釋,必然編譯不能經過github
解決:禁止在package.json中註釋web
說明:在最開始作項目時,因爲本地已經全局安裝過了對應的依賴包,所以沒有再從新在本地安裝,致使運行時報錯,全局安裝版本與本地依賴的版本不一致致使。算法
解決:每個項目中,全部的依賴包均在本地安裝,依賴狀況經過npm install *** --save -dev
注入package.json
中,其中一些環境之外的依賴,好比第三方庫express
等能夠經過npm install *** --save
安裝。express
全部的依賴包都在本地安裝是一個好習慣,由於這樣能夠隨時打包帶走與從新裝箱。npm
css-loader
省略-loader
帶來的問題說明:在老版本的webpack中,常常會用省略的寫法來寫loader,好比
loaders: [{ test: /\.css$/, loader: "style!css" }],
可是,使用此種寫法後,編譯時會報錯。
解決:如今新版本中,已經不容許省略了,好比使用全稱,好比:
loaders: [{ test: /\.css$/, loader: "style-loader!css-loader" }],
require(css)
後,樣式嵌入在js中,沒有獨立的css文件說明:webpack的默認設置中,若是沒有引入特殊的第三方插件,在js中require的css文件是會自動寫入到相應打包出的js中的,這樣一來有一些缺點:
解決:須要引入一個第三方插件extract-text-webpack-plugin
,具體以下:
//頭部引入css打包插件 const ExtractTextPlugin = require("extract-text-webpack-plugin"); //聲明對應的loaders loaders: [{ test: /\.css$/, //請注意loader裏的寫法,有一些低版本的例子中是過期的寫法 loader: ExtractTextPlugin.extract({ fallback: "style-loader", use: "css-loader" }) }], plugins: [ ... //這樣會定義,全部js文件中經過require引入的css都會被打包成相應文件名字的css new ExtractTextPlugin("[name].css"), ],
注意,以上loaders和plugins中都必須聲明,缺一不可
說明:最初在引用ExtractTextPlugin 插件時,使用了以下寫法,致使了報錯
loaders: [{ test: /\.css$/, loader: ExtractTextPlugin.extract(["style-loader","css-loader"]) }],
解決:緣由是這種寫法已通過時,根據命令臺中的提示,修改成最新寫法便可:
loaders: [{ test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: "style-loader", use: "css-loader" }) }],
require(html)
不會輸出成html說明:在使用webpack時,習慣性的用了萬物皆模塊這個概念,因而在js中引入html,以下:
//***.js中 require('./index.html') ...
結果是並不會生成一個index.html的文件,而是會將html代碼嵌入到js中,做爲模塊代碼而存在。
解決: 通常webpack項目中,會用htmlPagePluginConfig
插件來引入html(這時候會給每個html制定一個入口js文件),而後接下來全部操做均可以從這個入口js文件中進行(好比引入css,好比邏輯操做)
須要注意的是,這個插件聲明html時,對應引入的js路徑必定要對,如:
{ template: 'pages/index.html', // 若是是隻聲明index,因爲路徑不對,則不會自動插入 chunks: ['js/index'], }
說明:開發過程當中使用的htmlPagePluginConfig
插件加載html,可是發現構建過程當中,html內部引入的img等標籤不會被自動替換。
解決:須要引入html-loader
插件,有了這個插件後,引入,默認會將html內部的img自動替換掉
link(css)
後,不會替換對應的css,或者是會報錯說明:正常開發是全部css都是在js中引入的,可是在某一次嘗試中,準備嘗試在html裏用原始的link方式引入css,並引入了html-loader,以下:
<meta charset="utf-8" /> <link rel="stylesheet" href="test.css" />
loaders: [{ test: /\.html$/, use: [{ loader: 'html-loader', options: { minimize: false, } }],
結果按上述的方法進行後發現對於的html裏的css路徑沒有替換,這時發現html-loader
默認是不會替換css,因而又作以下改動
loaders: [{ test: /\.html$/, use: [{ loader: 'html-loader', options: { minimize: false, //開啓link的替換 attrs: ['img:src', 'link:href'] } }],
可是採用上述配置後,提示:Error: "extract-text-webpack-plugin" loader is used without the corresponding plugin
解決:webpack中ExtractTextPlugin須要配合js模塊化引入css使用。
若是想要實現html內部linkcss,目前沒有找到完美的解決方法,只知道使用webpack構建項目時,css都經過js require
引入就不會有錯了
.min.css
重複壓縮會報錯說明:在項目中引入第三方lib文件後,發現,若是引入的文件自己已經壓縮過了(如min.css文件),這時候再採用壓縮配置css-loader?minimize
,則會報錯
解決:採用了正在表達式進行了過濾,含有.min.css的文件不會壓縮,其它css則會壓縮,以下:
loaders: [{ //20170314更新:如下是錯誤寫法,好比common.css也沒法匹配的 //test: /[^((?!\.min\.css).)*$]\.css$/, //如下是正確寫法 test: /^((?!\.min\.css).)*\.css/, loader: ExtractTextPlugin.extract({ fallback: "style-loader", use: "css-loader?minimize&-autoprefixer" }) }, { test: /\.min\.css$/, loader: ExtractTextPlugin.extract({ fallback: "style-loader", use: "css-loader" }) }],
20170320更新
最終發現重複壓縮錯誤的緣由是由於.min.css
文件中包含以下代碼:
background-image: url('data:image/svg+xml;charset=utf-8,<svg viewBox=\'0 0 120 120\' xmlns=\'http://www.w3.org/2000/svg\' xmlns:xlink=\'http://www.w3.org/1999/xlink\'><defs><line id=\'l\' x1=\'60\' x2=\'60\' y1=\'7\' y2=\'27\' stroke=\'%236c6c6c\' stroke-width=\'11\' stroke-linecap=\'round\'/></defs><g><use xlink:href=\'%23l\' opacity=\'.27\'/><use xlink:href=\'%23l\' opacity=\'.27\' transform=\'rotate(30 60,60)\'/><use xlink:href=\'%23l\' opacity=\'.27\' transform=\'rotate(60 60,60)\'/><use xlink:href=\'%23l\' opacity=\'.27\' transform=\'rotate(90 60,60)\'/><use xlink:href=\'%23l\' opacity=\'.27\' transform=\'rotate(120 60,60)\'/><use xlink:href=\'%23l\' opacity=\'.27\' transform=\'rotate(150 60,60)\'/><use xlink:href=\'%23l\' opacity=\'.37\' transform=\'rotate(180 60,60)\'/><use xlink:href=\'%23l\' opacity=\'.46\' transform=\'rotate(210 60,60)\'/><use xlink:href=\'%23l\' opacity=\'.56\' transform=\'rotate(240 60,60)\'/><use xlink:href=\'%23l\' opacity=\'.66\' transform=\'rotate(270 60,60)\'/><use xlink:href=\'%23l\' opacity=\'.75\' transform=\'rotate(300 60,60)\'/><use xlink:href=\'%23l\' opacity=\'.85\' transform=\'rotate(330 60,60)\'/></g></svg>');
因此包含這種代碼的css使用css-loader的minify時會報錯,解決方法是暫時將這類的css單獨放入文件中,而且不進行minify
說明:在將項目劃分目錄結構後,html內和css內都有引用img或font,採用html-loader
替換html內部資源,以後發現構建出來後的文件中,img和font等資源的引用路徑不對。如:
原本應該是路徑 ../img.***.img 結果直接就變成了 img/***.img 致使路徑不一致
解決:默認打包路徑沒法替換爲相對路徑。這時候須要引入publicPath
這個變量,將全部的資源用全局路徑替換,如:
output: { // 用來解決css中的路徑引用問題 publicPath: config.publicPath, },
以上publicPath由開發者自身根據實際狀況進行配置,通常是指向項目的發佈路徑根目錄,好比http://localhost:8080/dist/
,能夠自由切換開發模式和發佈模式
webpack-dev-serve
配置錯誤帶來的問題說明:在使用webpack-dev-serve
時遇到了以下問題:
one:
webpack-dev-server --port 8082
便可開啓服務,而且自動監聽進行刷新(而且支持iframe刷新與inline刷新)publicPath
後,默認的服務端配置,啓動後不會自動監聽進行刷新devServer
和構建的路徑outputPath不一致致使的,如Project is running at http://localhost:8082/ webpack output is served from http://localhost:8080/dist/
//dev版纔有serve devServer: { historyApiFallback: true, hot: false, //不使用inline模式,inline模式通常用於單頁面應用開發,會自動將socket注入到頁面代碼中 inline: false, //content-base就是 codeResource -須要監聽源碼 contentBase: path.resolve(__dirname, config.codeResource), watchContentBase: true, // 默認的服務器訪問路徑,這裏和配置中一致,須要提取成純粹的host:ip public: /https?:\/\/([^\/]+?)\//.exec(config.publicPath)[1] },
two:
contentBase:"dist"
,可是卻發現修改dist裏的任何文件,服務端都不會刷新three:
inline
和hot
,可是熱更新無效HotModuleReplacementPlugin
,須要以下聲明new webpack.HotModuleReplacementPlugin()
four:
ERR_NAME_NOT_RESOLVED
,不能實時刷新,一直都沒法找到緣由//正常設置 localhost:8080 //個人設置 http://localhost:8080
Project is running at http://http://localhost:8080/
,因此只須要改爲正常配置便可iframe
刷新,inline和hot都要是falsefive:(20170322更新)
webpack-dev-server
默認只能在localhost訪問,換爲內網ip就不行了(好比192.×××,就算是本機也不行的)//這個配置能夠運行其它機器訪問 host: '0.0.0.0', //或者運行時 -- host 0.0.0.0
hash
與chunkhash
形成的問題說明:項目發佈時,爲了解決緩存,須要進行md5簽名,這時候就須要用到hash
和chunkhash
等了,可是卻遇到了以下問題:(hash系列問題的解決大多參考了參考來源中的博客)
one:(hash問題)
hash
對js和css進行簽名時,每一次hash值都不同,致使沒法利用緩存hash
字段是根據每次編譯compilation的內容計算所得,也能夠理解爲項目整體文件的hash值,而不是針對每一個具體文件的。(因此每一次編譯都會有一個新的hash,並不適用)chunkhash
(js和css要使用chunkhash),chunkhash
的話每個js的模塊對應的值是不一樣的(根據js裏的不一樣內容進行生成)two:(img的chunkhash問題)
chunkhash
,可是又有了新的問題-img和font等資源中,使用chunkhash
會報錯chunkhash
只適用於js和css,img中是沒有這種東西的,仍然須要用到hash
(這個hash有點區別,每個資源自己有本身的hash)three:(chunkhash重複問題)
chunkhash
是相同的,致使沒法區分css和js的更新,以下index2-ddcf83c3b574d7c94a42.css index2-ddcf83c3b574d7c94a42.js
*解決:css是使用ExtractTextPlugin
插件引入的,這時候可使用到這個插件提供的contenthash
,以下(使用後css就有獨立於js外的指紋了),
new ExtractTextPlugin("[name]-[contenthash].css")
chunkhash
變更(緣由估計是webpack內置的算法變爲了只計算js chunk),因此css請務必使用contenthash
,不然修改後沒法生成新的簽名,而是會覆蓋之前的資源UNMET PEER DEPENDENCY node-sass
,依賴包安裝失敗說明:剛開始試了下,sass的編譯,裏面有引入node-sass
這個依賴包,以後基於這個出現了一些問題
one:(安裝node-sass
失敗)
sass
時,依賴了這個包,可是用npm安裝時,安裝失敗cnpm
安裝,安裝cnpm以下npm install -g cnpm --registry=https://registry.npm.taobao.org
two:(node-sass
引發的其它安裝包安裝失敗)
+-- UNMET PEER DEPENDENCY node-sass@^4.0.0 -- webpack-dev-server@2.4.1 extraneous
sourceMap
配置帶來的問題說明:在使用sourceMap時,遇到了如下問題
one:(uglify壓縮去掉了sourceMap)
sourceMap:true,
sourceMapFilename:'maps/[name].map'
,將map文件放入maps文件夾中htmlPagePluginConfig
配置帶來的問題20170318更新
說明: 同時引入了html-loader
和html-webpack-plugin
後,兩個插件都設置了minify屬性,則會編譯生成時報錯,錯誤配置以下:
loader: 'html-loader', options: { minimize: config.isRelease ? true : false, } new HtmlWebpackPlugin({ *** minify: config.isRelease ? { collapseWhitespace: true, collapseBooleanAttributes: true, removeComments: true, removeEmptyAttributes: true, removeScriptTypeAttributes: true, removeStyleLinkTypeAttributes: true, minifyJS: true, minifyCSS: true }: null, })
解決:只須要將HtmlWebpackPlugin中對應的minify屬性去掉便可。
webpack
中JS手動引入的圖片問題20170318更新
說明: webpack是萬物皆模塊,但也就是說,不經過require引入的就不會算成模塊了(插件中的另算,那是處理過的)。因此,在JS中手動引入圖片時會遇到問題就是對應的圖片並不會被打包,致使以後找不到路徑。以下:
var GalleryData = [{ id: "testgallery1", title: "", //爲空 //保持目錄結構 url: "../../static/img/gallery/img_testgallery1.jpg" }, { id: "testgallery2", title: "", //爲空 url: "../../static/img/gallery/img_testgallery2.jpg" }];
以上的url就是引入的源碼本地圖片,可是卻發現並不會被打包出來。
解決:
static
文件夾做爲靜態資源,用copy-webpack-plugin
插件提取出來(這時候須要遵照的一個約定就是static
文件夾下的是專門給js引入或者外部資源訪問的,平時正常的css,html中的引入請放入其它文件夾中,好比img
,避免相互影響,這就是約定大於配置)var imgUrl = require('./images/bg.jpg'), imgTempl = '![]('+imgUrl+')';
本次進行webpack學習時。依次安裝功能遞增,按部就班的寫了多個demo(每個都可正常運行),每個demo都有自身的READEME.MD
說明,目錄結構以下;
├── 01helloWorld # 入門hellworld,一個html,一個js,一個css,css默認嵌入在js中,html採用`HtmlWebpackPlugin`加載 ├ ├── 02helloWorld2 # 基於第1個進行拓展,css使用`ExtractTextPlugin`單獨打包成一個文件 ├ ├── 03pageWithSingleJsAndCss # 基於第2個進行拓展,示例頁面由一個變爲多個,而且抽取了通用配置文件`common.config` ├ ├── 04pageWithStaticResource # 基於第3個進行拓展,增長了`html-loader`替換靜態資源,解決了css重複壓縮報錯問題,使用`publicPath`,解決資源文件引用路徑問題,增長了`webpack-dev-server`配置 ├ ├── 05withCommonChunk # 基於第4個進行拓展,增長了`CommonsChunkPlugin`提取公告js和css,增長了`UglifyJsPlugin`,修改了一些配置,更好應用於項目 ├ ├── 06withHashStaticAndRelease # 基於第5個進行拓展,增長了`CopyWebpackPlugin`複製靜態資源,增長了`chunkhash`,`contenthash`等指紋簽名功能,增長了`alias`別名設置,增長了release版本和dev版本的開關 ├ ├── 07withLocalServer # 基於第6個進行拓展,增長了一個`api-server`,來寫本地測試接口(已經進行了跨域配置) ├ └── 08withFamilyBucket # 基於第7個進行拓展,webpack全家桶項目,增長了`source-map`,增長了`assets-webpack-plugin`等等
系列demo的源碼地址是: https://github.com/dailc/webpack-freshmanual
初次發佈2017.03.13
於我的博客