從Grunt->gulp->webpack,再到目前當紅明星rollup,前端模塊打包技術突飛猛進,webpack在今年1月份和6月份左右接連更新了v2和v3版本,爲了減小冗餘模塊,縮減bundle文件大小,webpack v2中也加入了tree-shacking,關於tree-shacking的特徵,能夠查看知乎如何評價 Webpack 2 新引入的 Tree-shaking 代碼優化技術?的討論。javascript
webpack在推出 v2以後迅速推出了v3版本,前段時間在知乎看到webpack做者LarkInn(他已經入駐sf)說後續會維持一個更快、一致和更穩定的發佈週期點這,難道要步Angular的後塵,做爲吃瓜羣衆表示很震驚,由於目前本身這邊項目webpack還停留在1.x版本,鑑於減小往後升級難度的想法,包括後續要作代碼和流程優化,我將webpack升級到了v2版本,在這主要想把這個升級過程遇到的一些問題分享出來,也方便你們踩坑。css
我能想到最簡單粗暴的作法就是直接把版本號改了下載新包看下會發生什麼。使用npm info webpack查看了一下版本的發佈信息,我更新到2.6.1版本,也是3.0前的最後一個版本,
期待一大堆報錯,很尷尬,發現webpack仍然使用1.x版本工做,也就是說包並無更新到,查了一下發現可能緩存形成的,使用npm cache clean但貌似也無論用,索性直接把node_module刪除了,從新安裝了一下模塊,打包,果真報錯了:html
報錯信息:前端
throw new WebpackOptionsValidationError configuration.resolve.extensions[0] should not be empty ...
提示是resolve.extensions寫法有問題,查看了一下extensions文檔java
This option no longer requires passing an empty string. 再也不支持空字符的寫法了。node
webpack1.x寫法:react
resolve: { root: .... extensions: ['', '.js', '.jsx', '.json'] },
webpack2寫法:webpack
resolve: { root: .... extensions: ['*', '.js', '.jsx', '.json'] },
報錯信息:git
configuration.resolve has an unknown property 'root'. These properties are valid: ...
原來root寫法也變了,root放在modules裏了。github
resolve: { modules: [ path.resolve(__dirname, 'src'), 'node_modules' ] } }
configuration.module.rules[0].use should be one of these: ...
接下來應該就是一堆loader寫法有問題,loader已經所有改爲了rules的寫法,而且爲了更加嚴謹?以前省略的loader後綴也得加上。因爲webpack2會自動給加載json文件,因此json-loader也就再也不須要了,查看這裏。
webpack1.x寫法:
webpackConfig.module.loaders = [{ test: /\.(js|jsx)$/, exclude: /node_modules/, loader: 'babel', query: '' }, { test: /\.json$/, loader: 'json' }]
webpack2.x寫法:
webpackConfig.module.loaders = [{ test: /\.(js|jsx)$/, exclude: /node_modules/, use: [{ loader: 'babel-loader', query: { cacheDirectory: true, plugins: [..plugins], presets: [..presets] } }] }]
css-loader,style-loader的配置:
webpack1.x寫法:
webpackConfig.module.loaders.push({ test: /\.css$/, exclude: null, loaders: [ 'style', 'css?modules&importLoaders=1&sourceMap&minimize', 'postcss?pack=default' ] })
webpack2.x寫法:
webpackConfig.module.rules.push({ test: /\.css$/, exclude: null, use: [ 'style-loader', { loader: 'css-loader', opitions: { modules: true, sourceMap: true, minimize: true, importLoaders: 1 } }, 'postcss-loader' ] })
==注意== 這裏css-loder的minimize默認是不開啓的,建議開啓壓縮能夠縮小文件大小。babel-loader的cacheDirectory開啓緩存能夠加速編譯過程。
修改原來的ExtractTextPlugin插件配置,對css文件進行處理,發現報以下錯誤:
報錯:
throw new Error("Chunk.entry was removed. Use hasRuntime()");
google了一下發現是當前版本(1.0.1)已經不適用, 升級到2.0。
webpackConfig.module.rules.push({ test: /\.css$/, use: extractText.extract({ use:[ { loader: 'style-loader' }, { loader: 'css-loader', options: { sourceMap: true, minimize: true, importLoaders: 1, modules: true } }, { loader: 'postcss-loader' } ] }) }) const extractText = new ExtractTextPlugin({ filename: 'styles/[name].[contenthash].css', allChunks: true, disable: __DEV__ }) webpackConfig.plugins.push(extractStyles)
postcss-loader插件配置會麻煩一些,有兩種方法:
一種是新建postcss.config.js文件
module.exports = { plugins: [ require('autoprefixer')({ /* ...options */ }) ] }
另外一種:
在webpack.config.js使用LoaderOptionsPlugin
webpackConfig.plugins.push( new webpack.LoaderOptionsPlugin({ options: { postcssLoader: () => { require('autoprefixer')(/* ...options */ ) } } }) )
DeprecationWarning: loaderUtils.parseQuery() received a non-string value which can be problematic, see https://github.com/webpack/lo...
貌似是loader-utils模塊引發的,沒有太明白問題出在哪,issues地址,我在webpack.config.js在加上下面代碼解決了。
process.noDeprecation = true
v1.x的時候你們都在吐槽webpack文檔問題,v2文檔確實提高很多,包括此次的升級若是跟着指南走,基本不會出什麼大問題,只是中途在配置ExtractTextPlugin、postcss插件時折騰了一些時間。完成此次的升級後,後續準備對流程再進一步的優化,縮減打包時間、減小bundle大小等。
這裏推薦一款插件webpack-visualizer-plugin,能夠將項目的打包狀況可視化,清楚瞭解到每一個模塊的大小、佔比,方便後續的優化。
若是對v2版配置還有問題的同窗,能夠查看我以前的一個v3.1版本的webpack.config.js。
附:
1.webpack v1至v2升級指南
官方webapck 1->2升級guides
另外一位同窗翻譯的升級指南中文版
2.幾篇關於升級優化的好文章:
Boost webpack build performance | Optimising webpack build performance | Webpack 構建性能優化探索
webpack2 終極優化
3.關於webpack的好文章集合(awesome-webpack)
蒐羅一切webpack的好文章好工具
(ps:第一次寫關於webpack的文章,難免有誤,請及時斧正)