叁叁肆

这个世界会好吗

453篇博客

webpack常用配置详解下篇

叁叁肆2018-11-30 10:49

此文已由作者刘诗川授权网易云社区发布。

欢迎访问网易云社区,了解更多网易技术产品运营经验。


HtmlWebpackPlugin

上面介绍的打包出的带有hash的js文件,如果手动去引入,那就太繁琐了,所以需要借助HtmlWebpackPlugin来自动注入打包出的脚本,常用配置如下:

plugins: [
    new HtmlWebpackPlugin({
        filename: 'index.html',//生成的html的文件名,可以带有子目录信息,默认就是index.html
        template: 'index.html',//生成的html所参照的模板文件的位置,模板中可以准写入一些需要预置的信息,比如要为Vue或者React准备的mount的节点,就需要先在模板中写入
        inject: true,//为true时,会自动把css文件写入head中(如果有用ExtractTextPlugin提取的话),把js文件写入到body最后
        chunksSortMode: 'dependency',//设置为dependency可以才能使得上面提到的CommonsChunkPlugin生成的3个js文件按照依赖的顺序依次写入html中
    })
]

Webpack异步加载模块

最后介绍一下webpack支持的异步按需加载模块机制。我们提供给用户的网页,如果想要在用户触发某些操作的时候,才去通过网络加载所需的模块,这样既可以加快用户首次页面加载的速度,也可以节省用户的流量。 webpack是同时支持CommonJsAMD模块化规范的,所以,有两种异步加载模块的写法:

function btnClickHandler(){
    /**
     * CommonJs异步加载方案
     */
    require.ensure([], () => {
        var utils = require('./js/utils').default;
        self.msg = utils;
    });


    /**
     * AMD 异步加载方案
     */
    require(['./js/utils'], utils => {
        self.msg = utils.default;
    })
}

比如放在一个按钮的点击事件的处理函数中,只有当用户点击该按钮,才会去下载这个./js/utils模块。而webpack在打包成,会自动识别这种写法的代码,把它们识别为需要按需异步加载的模块,单独进行打包,这种按需加载的文件,就是通过上文中webpack配置中output.chunkFilename来指定文件名的格式。 当然,也可以通过require.ensure()方法的第三个参数来指定这个chunk的名称,在output.chunkFilename中就可以使用'[name].[chunkhash:7].js'来指定这些异步模块包的文件名了。 异步加载文件的过程展示如下: 


Webpack 2

webpack2在前段时间发布了,相对于1.X版本有了一些改变和优化,这里简单介绍一些常用的吧。

resolve.root, resolve.fallback, resolve.modulesDirectories

这三项被合并成了一个配置项:resolve.modules,我之前就觉得那三项的配置有点混乱,webpack2也为此做了精简:

resolve: {
    modules: [
        path.join(__dirname, "src"),
        "node_modules"
    ]
}

modules.preLoaders, modules.loaders, modules.afterLoaders

这三项也被精简合并成了一项:modules.rules,而且不再允许省略-loader扩展名(除非特意去配置),loader 的参数配置只能写在 rule.options内部不能写在外面:

module: {
    rules: [{
        test: /\.css$/,
        use: [
            { 
                loader: 'style-loader' 
            }, 
            {
                loader: 'css-loader',
                options: {
                    modules: true
                }
            }
        ]
    }]
}

ExtractTextWebpackPlugin

ExtractTextWebpackPlugin 1.x版本在webpack2中将无法使用,适配webpack2的ExtractTextWebpackPlugin配置方式有所变化:

module: {
    rules: [
        test: /.css$/,
        loader: ExtractTextPlugin.extract({
            fallbackLoader: "style-loader",
            loader: "css-loader",
            publicPath: "/dist"
        })
    ]
},
plugins: [
    new ExtractTextPlugin({
        filename: "bundle.css",
        disable: false,
        allChunks: true
    })
]

webpack2模块按需加载

webpack2现在支持ES2015import()模块异步加载语法,而且它会返回一个Promise对象,这样模块异步加载出错也能有方法捕捉了:

function btnClickHandler() {
    import('./js/utils').then(module => {
        return module.default;
    }).catch(err => {
        console.log("Chunk loading failed");
    });
}

import()加载机制还支持表达式写法:

function route(path, query) {
    return import(`./routes/${path}/route`)
        .then(route => new route.Route(query));
}

webpack2将会把所有可能符合表达式的模块都另外打包起来。 要使用webpack2的这个特性,需要加一个配置项,使的Babel不会将这些代码转化为ES3的代码。

{
  "presets": [
    ["es2015", { "modules": false }]
  ]
}

但是import()不具备上文所提到的require.ensure()方法的第三个参数可以指定chunkname的功能,如果需要用到这个功能,还是可以得使用require.ensure()

模板字符串支持

就像上面一点中使用到的,webpack2现在支持ES2015中的模板字符串语法了。

function route(path, query) {
    return import(`./routes/${path}/route`)
        .then(route => new route.Route(query));
}

配置项Promise化

webpack1的配置文件只能是一个配置对象,webpack2支持从配置文件中返回一个Promise对象,这就是使得我们可以更直观的在一个文件中支持多种环境的配置,而不需要像有的项目那样通过不同的配置文件来管理。

module.exports = function() {
    // 异步读取语言包
    return fetchLangs().then(lang => ({
        entry: "...",
        // ...
        plugins: [
            new DefinePlugin({ LANGUAGE: lang })
        ]
    }));
};


以上就是我使用webpack的一点学习经验,并不全面,不对之处请帮忙指出,谢谢。


相关文章:webpack常用配置详解上篇


免费领取验证码、内容安全、短信发送、直播点播体验包及云服务器等套餐

更多网易技术、产品、运营经验分享请点击