webpack 3.X學習之多頁面打包

weixin_33797791發表於2017-12-29

作者網站原文:http://hawkzz.com/blog/blog/1514542087911

簡介

我們開發不可能只寫一個頁面,每次都要寫很多頁面,這時為了開發效率,我們使用前端自動化工具webpack,那麼webpack是如何打包頁面的呢?又是如何打包多頁面的呢?

單頁面打包

我們知道要打包單頁面的方法,很簡單,配置入口,和html外掛,

const HtmlWebpackPlugin = require('html-webpack-plugin');

const config = {
    entry:{
        index:'./src/index.js'
    },
    output:{
        path: path.join(__dirname, 'dist'),
        filename: 'js/index.js'
    }
    ...
    plugins:[
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: './src/index.html',
            hash: true,
            minify: {
                removeAttributeQuotes:true,
                removeComments: true,
                collapseWhitespace: true,
                removeScriptTypeAttributes:true,
                removeStyleLinkTypeAttributes:true
            }
        })
    ]
}

上面的配置就是打包一個單頁面的程式碼,具體配置項的意思請參考HTMLWebpackPlugin;

如何打包多頁面

在學了webpack之後,我的感受是我會配置webpack了,也能執行了,但是學習的過程中都是單頁面的,那麼多頁是如何打包的呢?其實多頁面的打包和單頁面的打包的原理是一樣的,只是多配置幾個對應的入口,和出口,以及HtmlWebpackPlugin物件;當然你完全可以像下面這樣:

const config = {
    entry:{
        index:'./src/index.js',
        info:'./src/index.js'
    },
    output:{
        path: path.join(__dirname, 'dist'),
        filename: 'js/[name].js'
    }
    ...
    plugins:[
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: './src/index.html',
            chunks:['index'],
            hash: true,
            minify: {
                removeAttributeQuotes:true,
                removeComments: true,
                collapseWhitespace: true,
                removeScriptTypeAttributes:true,
                removeStyleLinkTypeAttributes:true
            }
        }),
        new HtmlWebpackPlugin({
            filename: 'info.html',
            template: './src/info.html',
            hash: true,
            chunks:['info'],
            minify: {
                removeAttributeQuotes:true,
                removeComments: true,
                collapseWhitespace: true,
                removeScriptTypeAttributes:true,
                removeStyleLinkTypeAttributes:true
            }
        })
    ]
}

細心的你肯定發現我改變了幾個地方,一是,把output.filename的‘js/index.js’變成了‘js/[name].js’,這是因為我們是多頁面,每個頁面對應相應的js這樣方便管理,二是,在HtmlWebpackPlugin物件中新增了chunks這個屬性,chunk屬性是讓你選擇對應的js模組;

上面這種寫法當然是沒有問題,這是隻有兩個頁面無所謂,那麼有十個甚至更多呢,我們一直做著重複的事,這不是我們程式設計師的風格,我們就是為了能夠偷懶才做程式設計師的不是嗎?(當然還有高工資(#.#)),接下來我們來抽離這些重複的事;

首先,我們通過Node的glob物件,來獲取我們存在的html或js;

/**
*
* @param {string}  globPath  檔案的路徑
* @returns entries
*/
function getView(globPath,flag){
    let files = glob.sync(globPath);

    let entries = {},
    entry, dirname, basename, pathname, extname;

    files.forEach(item => {
        entry = item;
        dirname = path.dirname(entry);//當前目錄
        extname = path.extname(entry);//字尾
        basename = path.basename(entry, extname);//檔名
        pathname = path.join(dirname, basename);//檔案路徑
        if (extname === '.html') {
            entries[pathname] = './' + entry;
        } else if (extname === '.js') {
            entries[basename] = entry;
        }
    });

    return entries;
}

既然,我們已經有了getView()函式,可以獲取html和js檔案,那麼我們就可以確定有多少個入口,和多少個頁面;

let entriesObj = getView('./src/js/*.js');

let config = {
    entry:entriesObj,
    ...
}

上面我們就配置好了入口,不需要我們手動新增了,有多少js就有多少入口;

let pages = Object.keys(getView('./src/*html'));

pages.forEach(pathname => {
    let htmlname = pathname.split('src\\')[1];
    let conf = {
        filename: `${htmlname}.html`,
        template: `${pathname}.html`,
        hash: true,
        chunks:[htmlname],
        minify: {
            removeAttributeQuotes:true,
            removeComments: true,
            collapseWhitespace: true,
            removeScriptTypeAttributes:true,
            removeStyleLinkTypeAttributes:true
        }
    }

    config.plugins.push(new HtmlWebpackPlugin(conf));
});

最後,我們獲取HTML頁面,和新增對應頁面的HTMLWebpackPlugin物件;

後記

通過以上的三個步驟,就可以配置好一個可以打包多頁面的webpack工具;本人的水平比較有限,在書寫的過程中,可能有很多說的比較模糊,請多多包涵,也請大神拍磚,多多指教

相關文章