最近在項目中使用了一下webpack,所以這里打算對目前了解的使用方法做一個小小的總結
為什么是webpack
- webpack一下自己就🔥了,這絕對是一個重要的原因。
- 然后我之前項目中都是通過requireJS,通過AMD來做到模塊化開發。webpak不僅支持打包,而且支持AMD 和 CommonJS 方式來做模塊化開發,所以打算嘗試一下webpack來實現模塊化。
- 我的需求簡單,適合新上手webpack,只需要生成上線目錄,實現模塊化,壓縮代碼等等
webpack實戰
webpack.config.js 一般寫法
開頭聲明對路徑相關的變量,以及引入依賴,包括webpack(非必須),以及需要的插件
然后,entry 聲明入口相關的如文件名,路徑等,output 聲明生成文件相關的路徑和文件名,module 中是針對不同文件進行處理的 loader 聲明,plugins 聲明了插件的具體使用。
壓縮代碼
這里使用webpack的內置的插件,我們寫在webpack.config.js 中的plugins 部分
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})
提取公共類庫
這部分我沒有用到,但也是基於webpack 內置的插件,目的是將用到的jquery 等第三方庫整合到一個文件,否則都合並到一個文件,會造成這個文件特別大
首先在entry 聲明第三方庫
entry: {
app: path.resolve(APP_PATH, 'index.js'),
//添加要打包在vendeors里面的庫
vendors: ['jquery', 'moment']
},
plugins: {
//把入口文件里面的數組打包成vendors.js
new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.js'),
}
css 單獨打包
有的時候需要將css 單獨打包,作為CDN,或者我這里的情況是是,頁面引入了很多的css js 文件,而我的js 在最后加載!所以如果是js 中引入的css ,那么會導致頁面在開始的時候沒有樣式,知道解析到我的js !所以這里將css 單獨打包,單獨在頁面引入!
首先需要安裝插件
npm install extract-text-webpack-plugin –save-dev
然后在webpack.config.js 中聲明插件
// 引入css 單獨打包插件
var ExtractTextPlugin = require("extract-text-webpack-plugin");
// 設置生成css 的路徑和文件名,會自動將對應entry入口js文件中引入的CSS抽出成單獨的文件
var packCSS = new ExtractTextPlugin('./css/[name].min.css');
在plugins 中引入並使用
plugins: [
packCSS
]
我們需要首先在js 中引用相應的css文件
require('./css/plan.css');
然后這個插件會自動將js中的css文件提取出來,生成單獨的文件
樣式的處理
安裝 css-loader style-loader
npm install css-loader style-loader --save-dev
css-loader會遍歷css文件,找到所有的url(...)並且處理。style-loader會把所有的樣式插入到你頁面的一個style
module: {
loaders: [
{
test: /\.css$/,
loaders: ['style', 'css'],
include: APP_PATH
}
]
}
圖片的處理
安裝 url-loader
npm install url-loader --save-dev
webpack.config.js
{
test: /\.(png|jpg)$/,
loader: 'url?limit=8192&name=images/[hash:8].[name].[ext]'
}
limit 設置一個閾值,小於這個值得圖片就會自動啟用 base64 編碼的圖片,大於這個值的圖片會打包到name 這參數對應的路徑,圖片名稱就會包括8位md5編碼 name 對應文件本來名稱,ext 對應擴展名
我在圖片這里遇到的問題和 css 類似,都是原本我是在 js 中引入 css img 等靜態資源。但是
因為我的頁面引入了很多的 css, js 文件,而我的js文件放到最后加載,所以會導致我的js引用的css img 在最后才加載。這會導致頁面開始的時候會出現沒有樣式,而圖片剛開始會顯示失敗的問題。
我本來也希望將 img 單獨打包,但是搜索也實踐了,沒有找到可靠地實現方式,於是我把圖片放到了其他公共資源目錄(,只好暫時出此下策了)(>_<)
一個頁面一個js 文件
我做的項目是多個頁面的,所以需要生成每個頁面對應的不同 js。這里的處理方法就是我們每個 js 都作為一個不同的入口文件現在 enrty 中。這樣設置好 output 中的公共路徑,就能得到不同的 js 文件。
entry: {
creative: './src/static/js/apps/idea.js',
plan: './src/static/js/apps/plan.js',
},
output: {
path: 'dist/',
filename: 'js/[name].min.js'
}
更新
代碼切分以及異步加載
今天遇到的問題是,我做的一個頁面是要分為四個步驟,每個步驟在進入下一步的時候需要對下一步的內容進行接口請求,頁面渲染和事件綁定等操作。
-
之前的做法
拆分了各個步驟對應模塊之后,我通過commonJS的方式在入口文件開頭引入了各個模塊
這時候是這樣的var stepOne = require('./mods/stepone.js'); var steptwo = require('./mods/steptwo.js'); ... // 使用的時候 stepone.checkOne();
這種做法,因為commonJS 的同步加載機制,會導致入口文件打包之后非常臃腫。在首屏,用到用不到處理代碼的都會在一開始就加載,嚴重影響了首屏加載時間。
-
代碼切分之后
我利用webpack的code splitting 特性,將各個步驟的代碼進行拆分,實現按需加載。這里主要利用了 webpack 的 require.ensure 函數實現的。非常方便,只需要把異步加載的代碼,放到 require.ensure 里面的回調函數就可以實現:
require.ensure(['./mods/stepone.js'], function(){ var stepone = require('./mods/stepone.js'); stepone.checkone(); }, 'stepone'); // 第三個參數設置打包名稱
這樣設置,webpack 就會單獨生成拆分的文件,我們還需要設置拆分文件的名字和路徑。這里我費了一番周折。
webpack 默認給拆分的文件用數字命名,如果我們自己不進行設置,會得到 1.min.js 這樣類似的文件。我們可以在 webpack.config.js 中,通過 output.chunkFilename 來設置分塊生成文件的名稱,分塊的路徑可以通過 output.publicPath 設置。這里一定要設置 publicPath,不然得到的路徑有可能不是我們上線打包的路徑。具體我的設置如下:
output: { path: path.join(__dirname, 'dist'), filename: 'js/apps/[name].min.js', publicPath: '/dist/', // 設置require.ensure路徑 chunkFilename: 'js/apps/[name].min.js' // 設置require.ensure 文件名 }
總結
webpack 使用起來感覺非常新穎,也容易入手!今天總結的多是入門的內容,后續還要繼續使用~
參考文章
- Webpack傻瓜式指南 (非常棒的教程,很詳細,保證你入門)
- 【前端構建】WebPack實例與前端性能優化
- webpack異步加載業務模塊
- webpack 學習筆記 03 Code Splitting