webpack學習筆記一(入門)


webpack集成了模塊加載和打包等功能 ,這兩年在前端領域越來越受歡迎。平時一般是用requirejs、seajs作為模塊加載用,用grunt/gulp作為前端構建。webpack作為模塊化加載兼容了amd/cmd模式,並且作為模塊化的資源可以是js/css/image  coffeescript/sass/less  ES2015 modles TypeScript 等功能非常強大,作為前端構建工具還可以和grunt/gulp配合一起使用。 配置文件webpack.config.js也是非常清晰。

一. 安裝webpack 

npm install webpack -g 全局安裝,這個時候可能會報錯:npm warn optional dep failed...等錯誤, 可能是nodejs版本太低了 ,nodejs.org下載最新安裝包即可 。

二. 命令行接口

1. 創建2個js文件

cats.js

var cats = ['dave', 'henry', 'martha'];
module.exports = cats;

app.js (主文件)

cats = require('./cats.js');
console.log(cats);

在命令行輸出 :

webpack ./app.js app.bundle.js

將會生成合並壓縮后的 app.bundle.js文件 。 可以直接當做nodejs模塊執行: node  app.bundle.js 看效果。

三. 使用配置文件

在項目根目錄下 npm init 創建package.json文件 。這時會提示輸入package相關信息。

npm install webpack --save-dev  下載webpack模塊並且將webpack加入package開發依賴(這樣其他合作開發者就可以直接npm install啦)。

在項目根目錄新建webpack.config.js 里面就是webpack的相關配置信息了 。

const webpack = require('webpack');  //加載webpack模塊
module.exports = {
    entry: './src/app.js',  //主入口文件
    output: {
        path: './bin',    //輸出文件目錄
        filename: 'app.bundle.js'   //輸出文件名
    },
    plugins: [
        new webpack.optimize.UglifyJsPlugin({  //使用uglifyjs插件
            compress: {
                warnings: false
            },
            output: {
                comments: false
            }
        })
    ]
};

webpack自帶了uglifyjs插件以及js loader,所以不需要自己添加額外的插件。

進入到項目根目錄在命令行直接運行webpack就行了。會看到在bin目錄多了個app.bundle.js文件。

目錄結構:

|--src

|--bin

|--node-modules

|--webpack.config.js

對於文件夾的命名,webpack官網是這樣說的:

In the wild, there are many project structures. Some projects use app instead of src. 
Some projects use dist or build instead of bin.
Projects with test usually use test, tests, spec, specs or colocate the test files in the source folder.

當需要加載其他特殊資源時需要下載相關的加載模塊,比如:babel-loader 加載es2015 ( ECMAScript 6 簡稱ES6 , JavaScript語言的新標准。當前版本的ES6是在2015年發布的,所以又稱ECMAScript 2015 ) ,如果要兼容舊版瀏覽器還需要下載babel-polyfill, 這樣就可以愉快的使用es6了。

四、輸出編碼格式

一般我們項目都是utf-8格式的,這時打包時默認輸出utf-8編碼格式的文件,如果需要輸出其他格式的文檔可以使用插件webpack-encoding-plugin ,插件支持的編碼格式

比如需要輸出GBK編碼文件,只需要在webpack.config.js里面配置:

plugins:[new encodingPlugin('GBK')]

但是如果項目文件本身是gbk編碼,而且有中文就比較麻煩了,如果還是按照上面的設置打包輸出gbk編碼,會發現中文亂碼了。一直沒找到好的方式解決這個問題,后來只能用nodejs先把需要打包的項目gbk文件copy一份寫入一個臨時目錄比如:webpack-temp,寫入的時候設置編碼轉換gbk->utf8 ,這樣在臨時目錄就有一份和項目文件一樣的文件,只是編碼是utf8 (中文是好的),把這個轉換的功能寫入一個轉換js模塊。 在webpack打包的時候就直接require該js模塊先執行轉碼,配置entry的時候路徑指向臨時目錄webpack-temp, 調用webpack-encoding-plugin輸出gbk編碼文件。大功告成,中文沒有出現亂碼了。 

轉碼關鍵代碼:

 1 var fs = require('fs'),
 2       iconv = require('iconv-lite');
 3 var pathname = root + '/' + file,
 4       from_code = 'GBK',
 5       to_code   = 'UTF8';
 6 fs.writeFile(pathname , iconv.decode(fs.readFileSync(pathname), from_code), {
 7                 encoding: to_code,
 8                 mode:'0666'
 9             }, function(err) {
10                 if (err) {
11                     throw err;
12                 }
13             });
View Code

 

轉碼方法可以參考下這個:https://github.com/baixuexiyang/coding

五、常用webpack命令

webpack         // 最基本的啟動webpack的方法
webpack -w      // 提供watch方法;實時進行打包更新
webpack -p      // 對打包后的文件進行壓縮
webpack -d      // 提供source map,方便調式代碼
webpack --progress //顯示進度
webpack --config xxx.js //調用不同的配置文件

對於比較長的命令可以寫在package.json文件的scripts里面,然后通過scripts指定了運行腳本命令的npm命令行縮寫,比如dev指定了運行npm run dev

"scripts": {
    "dev": "webpack-dev-server --inline --hot --no-info"
}

 

六、使用sourcemap 

devtool: "#source-map",   //使用#source-map打包會有點慢,使用#eval-source-map打包生成的文件放在一起體積會增加很多,不適合生產環境

devtool到底用哪個配置可以參考下這個:https://segmentfault.com/a/1190000004280859  ,不過寫的還是比較模糊..

打開開發工具並且設置了Enable JavaScript source map選項才會下載map文件到本地, 打開source選項看到有webpack:// ,map文件就在里面。 設置了sourcemap需要把開發工具關了重新打開

 

  在斷點調試的時候發現要先在壓縮的文件斷點,然后點擊 step over next function ... ,再點擊exec... 就進入了map文件斷點 。(有點奇怪)

sourcemap 報錯問題可以參考這個:https://github.com/webpack/webpack/issues/91 

 七、使用CommonsChunkPlugin

 當有多個文件require一個相同的文件的時候,在打包的時候我們可以把這個相同的文件提煉出來生成獨立的common.js文件。

//a.js
require('./c.js');
...
//b.js
require('./c.js');
...
//c.js
var obj = ['132','test',13123];
module.exports = obj;

webpack相應配置:

plugins: [
        new webpack.optimize.CommonsChunkPlugin({
            name: 'commons',
            filename: "commons.js", //輸出的文件名
            minChunks: 2  //指一個文件至少被require幾次才會被放到CommonChunk里,這一項一定要設置否則生成的common.js不會包含公共的文件
            // (Modules must be shared between 2 entries)

            // chunks: ["pageA", "pageB"], //只提煉A、B里的公共文件
            // (Only use these entries)
        })
    ]

選項:

name:chunk的名稱,如果這個chunk已經在entry中定義,該chunk會被直接提取;如果沒有定義,則生成一個空的chunk來提取entry中其他所有chunk的公共代碼。 

filename:指定提取出的公共代碼的文件名稱。未定義時使用name作為文件名。如果代碼要壓縮,指定filename屬性會有點問題發現代碼沒壓縮,待查看

chunks:指定要提取公共模塊的chunks,指定的chunk必須是公共chunk的子模塊,如果沒有指定則使用所有entry中定義的入口chunk。

minChunks:在一個模塊被提取到公共chunk之前,必須被最少minChunks個chunk所包含。(一個模塊至少要被minChunks個模塊所引用,才能被提取到公共模塊。)
該數字必須不小於2或者不大於chunks的個數。默認值等於chunks的個數。

如果指定了Infinity,則創建一個公共chunk,但是不包含任何模塊,內部是一些webpack生成的runtime代碼和chunk自身包含的模塊(如果chunk存在的話)。

也可以給 minChunks 傳入一個函數。這個函數會被 CommonsChunkPlugin 插件回調,並且調用函數時會傳入 module 和 count 參數。

參考:

https://doc.webpack-china.org/plugins/commons-chunk-plugin 

http://www.mamicode.com/info-detail-2042904.html

http://blog.csdn.net/liangklfang/article/details/54931523  //

 

通常用這個插件提取公共入口模塊,以及項目的庫文件(vue/vuex/vue-router等),webpack相關的運行公共代碼(webpackJsonp定義,_webpack_require定義等)

//webpack入口配置
entry : {
        vendor : ['vue','vue-router','vuex'], //項目中不變的庫文件,可以單獨打包到獨立文件
        main : ['./app/js/main.js'] //main.js里包含vue/vuex/vue-router等包引入,通過common插件提取到vendor
    }

......
//經常使用vendor提取項目的庫或插件文件, 用manifest提取入口的公共模塊,包括webpack運行時的公共部分文件。 所以使用的時候注意manifest要在頁面腳本最前面引入,其次再引入vendor
new webpack.optimize.CommonsChunkPlugin({
            name:[ 'vendor','manifest'], //會到入口配置檢查有沒有對應的chunk, 如果有則直接提取入口的chunk到該commonchunk, 否則創建新的commonchunk
            minChunks: Infinity,
        }),

//或分開寫:

new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor', //提取入口的vendor chunk 和 main chunk里引入的公共文件到vendor文件
            minChunks: Infinity, //可以是一個function ,根據function判斷chunk文件路徑和文件目錄信息,根據這些信息判斷是否要創建chunk
        }),
        new webpack.optimize.CommonsChunkPlugin({
            name: 'manifest', //創建新的chunk, 提取所有入口的公共部分(webpack相關運行代碼和其他公共模塊)
            minChunks: Infinity,
        }),

 

 

 

八、緩存和html-webpack-plugin

在處理緩存問題時,希望文件內容改變時更新緩存,可以用到chunkhash更改文件名,在輸出文件時配置下文件名即可:

output:{
      path:'./bin',
      filename:'[name]-[chunkhash:8].js'    //chunkhash默認會根據內容生成20位的hash, 可以通過配置參數控制位數。hash是每次webpack編譯生成文件時都會變化,這里用chunkhash
},

這樣當文件內容改變時文件名字就變化了,如果手動去改引用的路徑太麻煩了。

可以用html-webpack-plugin來解決這個問題, 這個插件可以根據模版生成一個新的文件,新文件包含相應的入口文件引用。

所以html模版文件我們需要兩份,一份是模板,一份是最終build的文件。模板里面也可以默認引入css和js,build的時候不會覆蓋默認的引入文件。

安裝html-webpack-plugin插件:

npm install html-webpack-plugin --save-dev

webpack.config.js配置:

var htmlWebpackPlugin = require('html-webpack-plugin');
......
entry:{
        'test':root_path + '/test.js',
        'aa': root_path + '/aa.js',
        'dd': root_path + '/dd.js'
    },
output:{
        path:'./bin',
        filename:'[name]-[chunkhash:8].js'
    },
plugins:[
        new htmlWebpackPlugin({
            filename: '../index2.html', //相對於output.path,產出路徑。
            inject: true, //true/body為插到/body前面
            template: 'index.html',  //模版文件,相對於config文件路徑
            chunks:['aa','test'], //需要引入哪些塊
            chunksSortMode:'dependency' //引入塊的排序,默認為auto, 改為dependency按照引入塊數組順序引入
        }),
        new htmlWebpackPlugin({
            filename: '../aa2.html', //相對於output.path,產出路徑。
            inject: true,
            template: 'aa.html',
            chunks:['aa','test','dd']
        })  //多個頁面需要new多個htmlWebpackPlugin實現
    ]

更多參考:https://www.npmjs.com/package/html-webpack-plugin,http://www.cnblogs.com/haogj/p/5160821.html,https://github.com/lcxfs1991/html-res-webpack-plugin/blob/master/README_ZH.md

 九、異步加載js模塊

語法: require.ensure(dependencies: String[], callback: function([require]), [chunkName: String])
dependencies: 依賴的模塊數組
callback: 回調函數,該函數調用時會傳一個require參數
chunkName: 模塊名,用於構建時生成文件時命名使用
注意:requi.ensure的模塊只會被下載下來,不會被執行,只有在回調函數使用require(模塊名)后,這個模塊才會被執行。

require.ensure會創建一個chunk,且可以指定該chunk的名稱,如果這個chunk名已經存在了,則將本次依賴的模塊合並到已經存在的chunk中,最后這個chunk在webpack構建的時候會單獨生成一個文件

比如:

require.ensure([], function(require){
        var ensure = require('./test/1.js');
        console.log(ensure);
    },'ensure2')

在webpack.config.js文件需要配置output

output: {
        path: __dirname+'/bin',
        filename: '[name].js',
        chunkFilename:'[name].js', //require.ensure異步請求設置生成的文件名,默認是數字,可以在require.ensure第三個參數配置這個名字
        publicPath:__dirname+'/bin/'  //require.ensure異步請求的模塊,在打包時提取出來生成文件存放在這個目錄
    },

 參考:http://blog.csdn.net/zhbhun/article/details/46826129

npm設置鏡像

1. 命令行:npm config set registry http://registry.npm.taobao.org 

2. 打開配置文件:C:\Users\Administrator\.npmrc  

修改其中內容為:registry = http://registry.npm.taobao.org

 參考文檔:

https://github.com/petehunt/webpack-howto

http://webpack.github.io/docs/usage.html

http://www.cnblogs.com/vajoy/p/4650467.html

https://www.npmjs.com/package/webpack-encoding-plugin

http://www.fantxi.com/blog/archives/webpack/

https://github.com/kairyou/demo/blob/master/webpack/webpack.cfg.js

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM