webpack搭建多頁面系統(三) 理解webpack.config.js的四個核心概念

webpack是須要本身編寫本身須要的一個配置對象,取決你如何使用webpack,下面指定了全部的可用的配置選項。
參考文檔:https://doc.webpack-china.org...css

webapck.config.jshtml

var path = require('path'); #使用Node內置的path模塊,並在它前面加上__dirname這個全局變量。能夠防止
不一樣操做系統之間的文件路徑問題,而且可使用相對路徑按照預期工做。
var webpackConfig = {
    devtool:'inline-source-map', //開發錯誤提示,嵌入到源文件
    entry:{ },  //string | object | array ;這裏應用程序開始執行;webpack開始打包
    output:{ },  //webpack 如何輸出結果的相關選項
    devServer:{ },  //開發服務器配置,
    module:{         //關於模塊配置
        rules:[]     //模塊規則(配置loader、解析器等選項)
    },
    plugins:plugins, //附加插件列表
}
module.exports = webpackConfig;

一、entry參數:入口文件配置

entry: //string | array | object。入口文件是應用程序的起點入口,從這裏應用程序啓動執行。若是傳遞的是一個數組,
        那麼數組的每一項都會執行。
規則:每一個HTML頁面都有一個入口起點。單頁應用(SPA):一個入口起點;多頁應用(MPA):多個入口起點。
命名:若是傳入一個字符串或字符串數組,chunk會被命名爲main。若是傳入一個對象,則每個鍵(key)是chunk的名稱,
        該值描述了chunk的入口起點。


在個人配置中,因爲是對多頁面的處理,因此採用entry:object;每個鍵(key)是chunk的名稱,同時又是chunk的入口起點。

webpack.config.js前端

//glob在webpack中對文件的路徑處理
var glob = require('glob');
const HtmlWebpackPlugin = require("html-webpack-plugin")
var webpackConfig = {
    /*webpack基礎配置*/
};    
//封裝方法,獲取指定路徑下的入口文件
//返回的結構 [ 'src/pages/contact/contact/index.js',
//            'src/pages/index/index/index.js',
//            'src/pages/join/join/index.js',
//            'src/pages/pagea/index/index.js' ]
function getEntries(globPath){
    //方法: glob.sync(pattern,[options]);該方法成功後,返回匹配搜索以後的數組,
    //沒有匹配返回一個空數組;pattern:'src/pages/**/index.js';這裏‘**’匹配模式表示的是
    位於src/pages/和/index.js的這兩層文件名
    var files = glob.sync(globPath),
    entries = {};
    files.forEach(function(filepath){
        //取倒數第二層(pages下面的文件夾)作包名
        var split = filepath.split('/');
        var name = split[split.length - 2];
        
        entries[name] = './' + filepath;
    });
    return entries;
};
//
var entries = getEntries('src/pages/**/index.js');
Object.keys(entries).forEach(function(name){
    //這裏循環輸出每個頁面的entry,
    webpackConfig.entry[name] = entries[name];
    //判斷是不是登錄頁面;由於登錄頁面和其餘頁面是兩個不一樣的模板
    //HtmlWebpackPlugin插件的詳細用法參考:https://segmentfault.com/a/1190000007294861
    if(name == 'login/login'){
        var plugin = new HtmlWebpackPlugin({
            //有模板生成的html文件名
            filename:'login.html',
            //登錄頁面的html模板
            template:'./src/login.html',
            inject:'body',
            chunks:['commons',name]
        });
    }else{
        var plugin = new HtmlWebpackPlugin({
            //有模板生成出來的html文件名
            filename:name + '.html',
            //除登錄頁面外,多個頁面使用同一個模板
            template:'./src/index.tmpl.html',
            inject:'body',
            chunks:['commons',name]
        })
    }
})

二、output參數:輸出文件配置

output包括一組選項,指示webpack如何去輸出、以及在哪裏輸出你的(bundle、asset和其餘你所打包或使用webpack載入的任何內容)。
經常使用的參數path、publicPath、filename、chunkFilename.
在個人webpack.config.js的配置中:
webpack.config.js:node

var webpackConfig = {
        devtool:'inline-source-map',
        entry:{ },
        output:{
            path:__dirname + 'build',
            filename: "js/[name].bundle-[chunkhash:8].js"
        },
        devServer:{ },
        module:{
            rules:rules
        },
        plugins:plugins
    }

output.path:string;output目錄對應一個絕對路徑 #path:path.resolve(__dirname,'bulid')
output.filename:string;此選項決定了每個輸出bundle的名稱。這些bundle將寫入到output.path選項指定的目錄下。
兩種狀況:
一、對於單入口起點,filename會是一個靜態名稱。filename:"bundle.js"。
二、對於多入口起點、代碼拆分或各類插件建立多個bundle,應該使用如下四種方式:react

(a)使用入口名稱:  filename:"[name].bundle.js";
 (b)使用內部chunk id : filename:"[id].bundle.js";
 (c)使用每次構建過程當中,惟一的hash生成:filename:"[name].[hash].bundle.js";
 (d)使用基於每一個chunk內容的hash: filename:"[chunkhash].bundle.js";

這裏涉及到緩存的知識:參考文檔:https://doc.webpack-china.org...
能夠經過命中緩存的技術,以下降網絡流量,使網站加載速度更快,若是咱們在部署新版本時不更改資源的文件名,瀏覽器就可能認爲它沒有更新,就會使用它的緩存版本,經過必要的配置,以確保webpack編譯生成的文件可以被客戶端緩存,而在文件內容變化後,可以請求到新的文件。
輸出文件的文件名(output.filename):
經過使用output.filename的不一樣的方式,能夠確保瀏覽器獲取修改後的文件。文檔中建議使用[chunkhash]替換,在文件名中包含一個chunk相關的哈希。jquery

三、經常使用loader(加載器)配置:module參數

Loaders的經常使用的加載器,參考文檔:https://doc.webpack-china.org...
安裝相對應的loader:webpack

npm install --save-dev css-loader;做用是指示webpack對每一個.css使用css-loader

使用Loader的方法:web

在應用程序中,有三種使用loader的方式:
一、配置(推薦):在webpaack.config.js文件中指定loader。
二、內聯:在每一個import 語句中顯示指定loader。
三、CLI: 在shell命令中指定它們。
配置[Configuration]:
    module.rules容許你在webpack配置中指定多個loader。這是展現loader的一種簡明方式,有助於使代碼變得簡潔。
    這是我常常用的書寫方式。
    module:{
        rules:[
            {
              test:/\.css$/,
              use:[
                  { loader: 'style-loader' },
                  {
                    loader:'css-loader',
                    options{
                        modules:true
                    }
                  }
              ]
            }
        ]
    }

下面介紹一些經常使用的loader的用法:shell

一、html-loader

html-loader 導出HTML爲字符串,須要引用靜態資源。
關於模板(templating)的有好幾種:html-loader、pug-loader、jade-loader、markdown-loader、posthtml-loader、react-markdown-loader、handlebars-loader、markup-inline-loader。npm

只介紹html-loader的使用:
參考文檔:https://doc.webpack-china.org/loaders/html-loader
安裝:
    npm install --save-dev html-loader
用法:
    默認狀況下,每一個本地的<img src="image.png">都須要require(require(./image.png))來進行加載。
    不過這須要file-loader或url-loader(這個後面有介紹)。
示例:
    module:{
        rules:[{
            test:/\.html$/,        #匹配以‘.html’結尾的模塊;
            loader:'html-loader',  #html-loader加載器
            options:{              #可選項(通常用於上線的webpack.build.config中)
                minimize: true,            #Boolean: 是否壓縮html
                removeComments: true,      #Boolean: 是否刪除註釋  
                collapseWhitespace: true, #Boolean: 是否刪除空格  
            }
        }]
    }

二、babel-loader

babel-loader 加載es2015代碼,而且將代碼轉譯爲ES5
參考文檔:https://doc.webpack-china.org...

安裝:
npm install --save-dev babel-loader babel-core babel-preset-env
用法:
在webpack配置對象中,須要添加babel-loader到module的loader列表中,像下面這樣:
module:{
    rules:[
        {
            test:/\.js$/,          #匹配以‘.js’結尾的文件
            loader:'babel-loader', #babel-loader加載器
            include:path.resolve(__dirname,'src'),   #只包括src 
            exclude:path.resolve(__dirname,'node_modules'), #排除node_module
            query:{
                presets:['preset-env']
            }
        }
    ]
}
babel-loader編譯很慢的,爲了確保轉譯儘量少的文件,可能使用/\.js$/來匹配,排除node_modules,配置exclude選項,
提升編譯速度。

三、less/css-loader

less/css-loader是對css的處理,下面分別介紹處理css時,用到的css-loader、less-loader、style-loader、postcss-loader。這幾種loader配合使用。
一次安裝全部的loader:
npm install --save-dev autoprefixer css-loader less-loader style-loader postcss-loader
less-loader:

你們能夠了解一些less的用法:http://less.bootcss.com/
less-loader: 把less編譯成css。使用css-loader或者raw-loader把它變成一個JS模塊,
並使用ExtractTextPlugin把它解壓到一個單獨的文件中,
這樣你的樣式不依賴於JavaScript。另外,less-loader並不會針對url()語法作特別的轉換,
若是想把url()語句裏涉及的文件(好比圖片、字體文件)也一併用webpack打包的話,就必須利用css-loader進一步處理。
參考文檔:https://doc.webpack-china.org/loaders/less-loader/
用法:
將css-loader、style-loader、less-loader鏈式調用,使用ExtractTextPlugin把它解壓到單獨的文件
webpack.config.js:
    const ExtractTextPlugin = require("extract-text-webpack-plugin");
    plugin = [...
     new ExtractTextPlugin("css/[name]-[chunkhash:8].css",{allChunks:false}), //css分離和壓縮
     ...
    ];
    module:{
        rules:[
            {
                text:/\.less$/,
                use:ExtractTextPlugin.extract({
                    fallback:"style-loader",
                    use:[
                        {
                            loader:'css-loader',
                            options:{
                                minimize:false;    #是否對css進行壓縮
                            }
                        },
                        {
                            loader:'postcss-loader', #自動添加瀏覽器前綴
                        },
                        {
                            loader:'less-loader'
                        }
                    ]
                })
            }
        ]
    }

css-loader:

用法:
css-loader解釋@import 和 url(),在import/require()後再解析它們。
選項:
    參考文檔:https://doc.webpack-china.org/loaders/css-loader/
    經常使用的就是是否對css進行代碼壓縮(Minification):minimize:Boolean;還有就是對url()語句的處理。
    在less/css裏url()語句,通常使用相對路徑的方式來指定文件路徑;請不要使用‘/’開頭
    (即相對於網站的根目錄,由於對於文件系統來講,這使人混淆)。

style-loader:

用法:
 經過注入<style>標籤將CSS添加到DOM,通常將style-loader與css-loader結合使用。
 webpack.config.js
     {
         module:{
             rules:[
                 test:/\.css$/,
                 use:[
                     { loader:"style-loader" },
                     { loader:"css-loader" }
                 ]
             ]
         }
     }

postcss-loader:

參考文檔:https://doc.webpack-china.org/loaders/postcss-loader/
用法:用於處理瀏覽器前綴,這裏使用postcss-loader須要在寫一個關於postcss.config.js的文件。
postcss.config.js:
    module.exports = {
        plugins:[
            require('autoprefixer')
        ]
    }
autoprefixer:將使用基於當前瀏覽器流行度和屬性支持的數據爲您應用前綴。

四、url/file-loader

用於打包處理圖片和字體。
安裝:
npm install --save-dev file-loader url-loader
file-loader:

參考文檔:https://doc.webpack-china.org/loaders/file-loader/
功能:將源文件遷移到指定的目錄,返回新的文件路徑。
用法:傳入name參數,該參數接受如下變量:
    以個人src/images/banner.jpg爲例;
    [ext]:文件的後綴名,‘jpg’。
    [name]:文件名自己,‘banner’。
    [path]:相對於當前執行webpack命令的目錄的相對路徑(不含文件名自己),在個人項目中源文件中的圖片是在‘src/images/**’中,在根目錄內執行webpack命令,也就是當前的上下文環境與src目錄同級
    [hash]:源文件內容的hash,用於緩存解決方案
    
webpack.config.js
     {
         module:{
             rules:[
                 test:/\.(png|jpg|gif)$/,      #匹配圖片資源
                 loader:'file-loader',
                 options:{
                     name:'images/[name].[ext]' #新文件的路徑
                 }
             ]
         }
     }
     當npm run build 後,個人圖片資源路徑是要拼上webpack配置中的output.publicPath參數;因此最終的圖片路徑是‘build/iamges/banner.jpg’,

url-loader:

參考文檔:https://doc.webpack-china.org/loaders/url-loader/
功能:在文件大小(單位byte)低於指定的限制時,將源文件轉換成DataUrl(聲明文件base64編碼)。圖片和字體文件的DataUrl都是能夠被瀏覽器所識別的,減小HTTP鏈接數。
參數:
    limit:Number;     #表示目標文件的體積小於限定的字節就用url-loader;大於限制字節時,就用file-loader來處理
    mimetype:String;   #指定文件的類型(不然從文件的擴展名)
    fallback:String;   #當文件大於限制時(以字節爲單位)爲文件指定加載程序
webpack.config.js
     {
         module:{
             rules:[
                 test:/\.(png|jpg|gif)$/,      #匹配圖片資源
                 loader:'url-loader',
                 options:{
                     limit:8192,
                 }
             ]
         }
     }

字體文件:

{
    test:/\.(eot|woff|woff2|ttf|svg)$/,
    loader:'url-loader'
}

四、plugins插件的介紹

有時候搞不明白 plugins 和 loaders的區別:
插件(plugins)是用來拓展webpack功能的,它們會在整個構建過程當中生效,執行相關的任務。
loaders是在打包構建過程當中用來處理源文件的(.js、.less、.html、img、字體),一次處理一個;
插件並不直接操做單個文件,它直接對整個構建過程做用。
webpack.config.js

var plugins = [
    new webpack.ProvidePlugin({
        $:"jquery",
        jQuery:"jquery",
        "window.jQuery":"jquery"
    }),
    new ExtractTextPlugin("css/[name]-[chunkshash:8].css",{allChunks:false}),
    new webpack.optimize.CommonsChunkPlugin({
        name:"commons",
        minChunks:2
    })
];

plugins:Array(數組),直接把要用的插件實例化以後丟進去就行了。

一、插件ProvidePlugin

關於插件ProvidePlugin自動加載模塊,而沒必要處處 import 或 require 。爲何要對jQuery進行全局定義?(我的水平有限。)
參考:https://segmentfault.com/a/11...
使用:jQuery
要自動加載jquery , 咱們能夠將三個變量都指向對應的node模塊:

new webpack.ProvidePlugin({
        $:"jquery",
        jQuery:"jquery",
        "window.jQuery":"jquery"
    }),

而後在咱們任意源碼中:

//in a module
$('#item');  //起做用
jQuery('#item'); //起做用
window.jQuery('#item'); //起做用
//$ 自動被設置爲「jquery」輸出的內容。

二、插件ExtractTextPlugin

做用:從bundle中提取文本(css)到單獨的文件。
安裝:npm install --save-dev extract-text-webpack-plugin
用法:

const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
    module:{
        rules:[
            {
                test:/\.css$/,
                use:ExtractTextPlugin.extract({
                    fallback:"style-loader",
                    use:"css-loader"
                })
            }
        ]
    },
    plugins:[
        new ExtractTextPlugin("css/[name]-[chunkhash:8].css",{allChunks:false}),
    ]
}

它會將全部的入口chunk(entry chunks)中引用的*.css,移動到和html頁面name對應的獨立分離的css文件。樣式不在內嵌到JS bundle中。若是你的樣式文件大小較大,就會作更快提早加載,由於css bundle 會跟js bundle 並行加載
參考文檔:https://doc.webpack-china.org...

二、插件CommonsChunkPlugin

CommonsChunkPlugin 插件,是一個可選的用於創建一個獨立文件的功能,這個文件包括多個入口chunk的公共模塊。經過將公共模板拆出來,最終合成的文件可以在最開始的時候加載一次,便緩存供後續使用,這個帶來速度上的提高,由於瀏覽器會迅速將公共的代碼從緩存中取出來,而不是每次訪問一個新頁面時,再去加載一個更大的文件。
例子:
公共chunk用於入口chunk:生成一個額外的chunk包含入口chunk 的公共模塊。

new webpack.optimize.CommonsChunkPlugin({
    name:"commons",          //公共chunk的名稱
    filename:"commons.js",    //公共chunk的文件名
    minChunks:3 ,             //模塊必須被三個 入口共享  
    chunks:["pageA","pageB"], //只使用這些入口chunks
})

三、插件HtmlWebpackPlugin

HtmlWebpackPlugin簡化了HTML文件的建立,加載本身的模板。
安裝:npm install --save-dev html-webpack-plugin
使用webpack生成HTML頁面的好處:
對於頁面相同或類似的部分,尤爲導航欄、側邊欄、還有頁尾,基本是一致的,若是須要修改頁面,傳統的都是每一個頁面都要修改,可維護性不好。

而「用webpack生成html頁面」,實際是依賴前端的模板引擎將頁面的各個部分拼接在一塊兒,達到公共模塊的複用。

利用html-webpack-plugin生成html頁面:

html-webpack-plugin的配置項:
    每個html-webpack-plugin的只對象實例化一個頁面,所以多頁面時,就要配置多個html-webpack-plugin的對象實例。
     Object.keys(entries).forEach(function(name){
         //每個頁面生成一個entry
         webpackConfig.entry[name] = entries[name];
         var plugin = new HtmlWebpackPlugin({
             //生成出來的html文件名
             filename: name + '.html',
             //這裏多個頁面使用一個公共模板
             template:'./src/index.tmpl.html',
             inject:'body',
             chunks:['commons', name]
         })
         plugins.push(plugin)
     }) 
entries是全部的入口*.js
    多頁應用經常使用的配置:
        filename:生成的網頁html文件的文件名,能夠利用‘/’來控制文件目錄結構,其最終生成的路徑,
        是基於webpack配置中的output.path的。
        template: 指定一個基於模板引擎語法的模板文件,若是想使用其餘格式的模板文件,
        須要在webpack配置裏設置好相應的loader,好比html-loader。若是是單頁應用,那麼這個參數
        不指定也能夠,但對於多頁應用來講,咱們依賴模板引擎給咱們拼裝頁面,這個參數很是重要。
        inject: 將加載的js文件插入到哪裏,默認是插入到<body>的末端,若是設置'head',
        則把<script>插入到<head>裏。
        minify: 生成壓縮後的html代碼。
        chunks:以數組的形式指定由html-webpack-plugin負責加載的chunk文件
相關文章
相關標籤/搜索