1

Webpack原理介绍和特点

clipboard.png

Webpack本质上是一个 前端模块化解决方案
该方案将所有文件均视为模块 方便使用者加载模块而不需要考虑模块间的依赖关系和同步异步加载
Webpack会把代码库中所以用到的模块进行静态分析(梳理依赖关系 不同类型模块交给对应的loader处理)编译打包
最后 分块传输 (按需进行懒加载 实际用到某模块的时候在进行增量更新)

Webpack有大量的loader和丰富的插件可以供开发者使用 并且Webpack对loader和插件的扩展性很好 配置十分方便

Webpack就有以下特点:

  1. 代码拆分:
    Webpack支持同步/异步两种组织模块依赖的方式

  2. loader:
    Webpack只支持原生的JavaScript模块 但是loader转换器可以将各种类型的资源转换成JavaScript模块资源 这样Webpack可以处理各种类型的资源

  3. 智能解析
    Webpack有个智能解析器 可以解析任何第三方库 无论他们的模块形式是CommonJS AMD还是原生的JS模块

  4. 插件系统
    丰富的插件系统 方便开发和使用开源的插件 满足各种需求

  5. 快速运行
    Webpack使用异步I/O和多级缓存提高效率 使得其可以快速增量编译

Webpack模块依赖解决方案

Webpack结合CommonJS和AMD的优缺点,开发时按照CommonJS的编写方式,利于开发者理解。编译时会给每个模块分配一个唯一的id,并通过id索引和访问模块,在浏览器中实行AMD规范,所以来的各个模块,均是模块的id,按需加载模块,实现两者的结合。

Webpack打包原理

clipboard.png

按照配置文件定义好的入口文件和出口文件和依赖模块 进行打包输出

Webpack配置

Webpack在执行的时候 除了命令行传入参数 还可通过指定的配置文件来执行 默认情况下会搜索当前目录下的webpack.config.js。该文件是一个nodejs模块 返回一个json格式的配置信息 或者通过 --config命令来制定配置文件。

下面是一个较为标准的配置项

var webpack = require('webpack');
var path = require('path');

module.exports = {
    // 入口文件 也就是那个文件需要打包编译
    // 基本就是一个项目的入口文件
    // 该文件所依赖的模块都将被打包
    entry: './entry.js',
    // 输出设置
    output: {
        // 输出文件的路径
        path: path.join(__dirname, 'dist'),
        // 输出文件的文件名
        filename: 'bundle.js'
    },
    // 依赖的模块 文件的选项
    // 处理项目中需要加载器的模块
    module: {
        // loaders是一个数组 用来处理webpack不能处理的非js模块
        // 每个loader都需要安装相应的loader
        // 每一项都是 json,
        // test 用来匹配相对应文件的正则表达式
        // loader 告诉webpack要利用哪种加载器来处理test所匹配的文件 值可以是字符串或数组 数组里每一项是字符串 表示多个处理器
        loaders: [
            // 处理css 的loader
            {
                test: /\.css$/,
                loader: 'style!css'
            },
            // 处理js和jsx文件的
            // exclude
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                loader: 'babel'
            },
            // 处理字体文件
            {
                test: /\.woff(\?.*)?$/,
                loader: 'url?name=fonts/[name].[ext]'
            },
            // 处理图片模块
            {
                test: /\.(png|jpg|gif)$/,
                loader: 'url?limit=8192&name=[name]_[hash:8].[ext]'
            }
        ]
    },
    // 添加插件
    plugins: [
        // 该插件自动将打包好的js插入到模板html中
        new HtmlWebpackPlugin({
            template: paths.client('index.html'),
            hash: false,
            favicon: paths.client('static/favicon.ico'),
            filename: 'index.html',
            inject: 'body',
            minify: {
                collapseWhitespace: true
            }
        })
    ],
    // 主要是分析依赖时的路径识别的配置
    resolve: {
        // 设置依赖的根路径 简化书写
        // 原来需要require('./js/a')
        // 配置之后 只需要写require('a')
        root: [
            path.resolve('./js/')
        ],
        // 支持匹配的文件的后缀
        extensions: ['', '.js', '.jsx', '.json']
    },
    // 根据不同需求常见 可以添加不同的配置项
    // eslint需要的配置项
    eslint: {
        formatter: require('eslint-friendly-formatter')
    },
    // vue需要的配置项 等等
    vue: {
        // ...
    }
};

以上是一个标准的webpack配置文件 并且可以满足大部分业务场景

对比其他工具

这里介绍三个对比工具 Browserify 和 Gulp
主要是三者侧重点不同 表格说明:

  Webpack Gulp Browserfiy
文件依赖分析 Webpack核心    
模块化开发 任何模块 支持AMD规范 支持CommonJS模块机进行转换包装
Sass/Less预编译 添加loader 添加模块 添加插件
HTML JS CSS 文件合并压缩 自动压缩合并 添加模块 自动压缩合并
版本控制 自动 自动 添加插件
服务重启 添加插件 自动  
学习成本 简单 简单但是繁琐 复杂

虽然经常经常拿三者进行对比 但是其实三者各有各的侧重点:

  1. Webpack
    Webpack诞生最晚 但是其智能的静态分析依赖是其核心 也是令人追捧的特点

其特点侧重于模块的打包和构建 将所有文件均当成模块 所以支持各种文件 十分方便

  1. Gulp
    Gulp侧重于开发流程的管理 使用Gulp实现项目从无到有到发布整个流程控制较方便

一套面向工作流程的工具 但是支持模块构建较差

  1. Browserfiy
    Browserfiy实际上是一个模块加载器 侧重于解决开发过程中的模块加载问题

在浏览器中使用Node.js模块为出发点的工具 支持CommonJS规范的模块

可以看到三者有各自诞生的目的 擅长领域不尽相同 但是功能相似 所以经常被拿来比较
实际上 Webpack是比Browserify兼容性更好的前端模块化解决方案
Gulp则是服务于前端开发自动化的工具

参考资料:

  1. Webpack中文指南:

  2. Webpack学习之路:

  3. 为何webpack风靡全球?三大主流模块打包工具对比:

  4. Webpack、Browserify和Gulp三者之间到底是怎样的关系?:

  5. Gulp和Webpack功能实现对比:


Aus0049
2.4k 声望231 粉丝

console.log(([][[]]+[])[+!![]]+([]+{})[!+[]+!![]])