webpack学习笔记1:基本概念

前言:
现在在日常的开发中,webpack已经是必不可少的东西了,现在的需求基本都是用webpack对资源进行打包整合,所以打算写一点关于webpack的东西,这是第一篇,主要是介绍一些基本的概念。

webpack的概念

众所周知,webpack是一个模块打包器,他会把项目里的各种资源进行统一打包,webpack打包的时候会递归的构建一个依赖图,每个用到的模块都在这个流程图上,最后输出一个javascript文件。

webpack由四个核心部分构成,分别是:

  • entry(入口)

  • output(出口)

  • loader(加载器)

  • plugin(插件)

entry入口

前边说过,webpack打包的时候会构建一个依赖图,而entry就是这个图的起点,webpack会知道,从哪个文件开始进行他的打包之旅。
webpack中有多种方法指定entry

简单语法

用法:

const config = {
    entry:'./path/app.js'
};

module.exports = config;

其实这是下边方式的简写

const config = {
    entry:{
        main:'./path/app.js'
    }
};

module.exports = config;

上边表示app.js文件是这个项目的入口文件,entry的值除了是一个字符串,还可能是一个数组。
如果你的项目很小,没有依赖其他的大型库,那么这种简单的写法是个很好的选择,从app.js开始,按照依赖图一次打包各个文件。
缺点是,这种配置缺乏一定的灵活性。

对象语法

前边说,简单写法缺乏灵活性,是因为,加入依赖了一个很大的库,比如react,每次执行打包的时候都需要把react打包一遍。

const config = {
    entry:{
        app:'./path/app.js',
        vendor:'./vendor.js'
    }
}

module.exports = config;

上面看起来项目有两个入口,app和vendor,两者独立于彼此,分别开始构建各自依赖的资源。这种方式常见于只有一个入口(app而不是vendor)的单页面(SPA)应用。
vendor是一些公共的库,不会发生轻易改变,甚至是不会改变,把他们提取出来会优化打包的效率,可以理解起到了一个缓存的作用。

多页面应用程序
const config = {
    entry:{
        page1:'./src/page1/page1.js',
        page2:'./src/page2/page2.js',
        page3:'./src/page3/page3.js'
    }
}

module.exports = config;

当项目是一个多页面应用的时候,需要的是多个webpack入口,所以就会有多个依赖图。这个我们看到,page1页面的入口是page1.js,其他两个页面的也是如此。
多页面不能用一个单个的入口的原因是,每次载入一个新的html,需要重新下载新的文件,所以页面需要哪个文件,就依赖哪个。
我们可以用CommonshunkPlugin来每个页面的共享代码创建bundle,提供复用的机制,提高效率。

output出口

有入口就有出口,在webpack中,output表示项目的出口,即打完包输出的文件。
即便有多个entry入口文件,可是在webpack中,只有指定一个输出配置

用法
const config = {
    entry:'./sec/app.js',
    output:{
        filename:'bundle.js',
        path:'./src'
    }
}

配置项是一个对象,对象里有两个属性。

  • filename:表示打包输出之后的文件名

  • path:表示打包输出的路径

多个入口的情况下

如何项目是有多个入口的情况下,这个时候使用占位符来确保每个文件有唯一的名称

const config = {
    entry:{
        app1:'./src/app1.js',
        app2:'./src/app2.js'
    },
    output:{
        filename:[name].js,
        path:__dirname+'/dist'
    }
}

在dist文件夹下,会有打完包之后的app1.js和app2.js两个文件。

loader加载

loader提供方法进行构建,包括去源代码进行转换,把不同的语言转成javascript,或者把图片转成dataUrl或者把sass文件中换成css。总之,loader是webpack的精髓,功能强大。

示例

比如,我们要用webpack加载css文件或者把typescript转成js,首先要安装对应的loader。

npm install css-loader --save-dev
npm install ts-loader --save-dev

然后指示每个css使用css-loader,每个ts使用ts-loader.

const config = {
    entry:'./src/app.js',
    output:{
        filename:'bundle.js',
        path:__dirname+ '/dist'
    },
    module:{
        rules:[
            {
                test:/\.css$/,
                use:'css-loader'
            },
            {
                test:/\.ts$/,
                use:'ts-loader'
            }
        ]
    }
}
使用loader的三种方式

在webpack中,有三种使用loader的方法,

  • 配置,在webpack的配置文件中配置(推荐)

  • 内联,在import中指定相关loader

  • CLI, shell命令使用(这个先不研究了)

配置

module.rules允许你在webpack中配置多个loader,这是最好的方式,可以让你一目了然的看到项目到底配置了哪些loader。

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

这是webpack2的语法。

内联

可以在import或者任何等价于import的语句中使用loader,不过用的很少,其语法是这样的

import style from 'style-loader!css-loader?modules'

尽量使用上一种配置的方法,因为可以减少代码量,每次都import引用也是一件很麻烦的事情。

loader解析

多数情况下,loader将会从模块路径开始解析,就是npm install安装的模块。
loader需要导出为一个函数,通常采用node兼容的js写法,有的时候也可以将自定义loader作为应用程序中的文件。通常情况下,采用xxx-loader的方式命名。

plugin插件

插件是webpack的支柱功能,一句话概括插件的作用就是做loader不能做的事情。

剖析

插件是一个拥有apply属性的js对象。apply会被webpack compiler调用,comliler是个对象,可以再在整个编译周期访问。

function plugin1(){
    ...
}
plugin.prototype.apply = function(compiler){
    compiler.plugin('run',function(compiler,callback){
        console.log('webpack构建开始了');
        callback();
    })
}
用法

由于插件是可能存在选项或者是参数的,所以在webpack文件中,需要在plugin属性里用new把需要的插件传进去,看下边例子

配置
const config = {
    entry:{
        app:'./src/app.js',
        vendor:'./src/vendor.js'
    },
    output:{
        filename:[name].js,
        path:__dirname+'/dist'
    },
    nodule:{
        loaders:[
            {
                test:/\.css$/,
                use:'style-loader!css-loader'            }
        ]
    },
    plugin:[
        new webpack.optimize.UglifyJsPlugin(),
        new HtmlWebpackPlugin({emplate:'./src/index.html'})
    ]
};

module.export = config;

后记

这篇文章主要介绍了一下webpack的基础概念,包括webpack配置文件的四个主要部分,entry,output,loader,plugin的写法。


张小草1018
285 声望8 粉丝