webpack 学习

23 阅读4分钟

webpack的定义:用于现代JavaScript应用程序的静态模块打包工具。(个人理解将资源是静态的,模块化的打包成一个或多个包)webpack中文文档

webpack的打包流程

  1. 初始化阶段:读取webpack.config.js中的配置参数和shell命令中传入的参数进行合并并得到最终打包的参数。
  2. 开始编译准备阶段:启动webpack,调用webpack()方法返回一个compiler方法,创建compiler(编译器)对象并开始注册各个webpack plugin。找到配置入口中的entry代码,调用compiler.run()方法进行编译,解析项目。
  3. 模块编译阶段:从入口文件(entry)开始解析,调用匹配文件的loaders对文件进行处理,并找到其导入的依赖模块,递归依赖分析,行程依赖关系树。
  4. 完成编译阶段:在递归完成后,对不同文件类型的依赖模块文件使用对应的Loaders(模块代码转换器)进行编译,得到模块之间的相互依赖关系。
  5. 输出文件阶段:整理模块之间的依赖关系,同事将处理后的文件输出到output的磁盘目录中。

核心概念:

  1. entry(入口)
  2. output(输出)
  3. loader (模块代码转换器)
  4. plugin(插件)
  5. mode(模式)
  6. brower compatibility(浏览器兼容性)
  7. environment(环境)

入口(entry)

**入口起点(entry point)**指示webpack应该使用哪个模块,来作为构件其内部依赖图(dependency graph)的开始。进入入口起点后,webpack会找出哪些模块和库是入口起点(直接和间接)的依赖。

默认值是./src/index.js,我们可以通过在配置文件中配置entry属性,来指定一个或者多个不同的入口起点。webpack.config.js

module.export = {
    ebtry:'./path/mypath/main.js'
}
  1. 配置单个入口(简写)语法  entry: string | [string]

    module.exports = {
        entry:'./path/index.js'
    }
    
    module.exports = {
        entry:['./path/main.js','./path/index.js']
    }
    
  2. 对象语法 entry:{<entryChunkName> string | [string]} | {}

    module.exports = {
        entry:{
            app:'./src/app.js'
        }
    }
    描述入口的对象:
    dependOn:当前入口所依赖的入口。它们必须在入口被加载前被加载。
    filename:指定要输出的文件名称。
    import:启动时需加载的模块。
    library:指定library选项,为当前entry构建一个library。
    runtime:运行时chunk(块)的名字。如果设置了,就会创建一个新的运行时chunk。
    publicPath:当该入口的输出文件在浏览器中北引用时,为它们指定一个公共URL地址。
    请查看output.publicPath(https://www.webpackjs.com/configuration/output/#outputpublicpath)
    module.exports = {
        entry:{
            a2:'./a',
            b2:{
        runtime:'x2',
        dependOn:'a2',
        import:'./b'  }    }
    }
    
  3. 常见场景   

    分离app(应用程序)和 vendor(第三方库)入口
    module.export = {
        entry:{
            main:'./src/app.js',
            vendor:'./src/vendor.js'
        }
    }
    多页面应用程序
    module.export = {
        entry:{
    pageOne:'./one.js',
    pageTwo:'./two.js'    }
    }
    

输出(output)

output属性告诉webpack在哪里输出它所创建的bundle(包),以及如何命名这些文件。主要输入文件的默认值是 ./dist/main.js,其他生成文件默认放置在 ./dist 文件夹中。

const path = require('path')

module.exports = {
    entry:'./path/mypath/index.js',
    output:{
        path:path.resolve(__dirname,'dist'),
        filename:'my.bundle.js'
    }
}
  1. 用法: 在webpack配置中,output属性的最低要求是,将它的值设置为一个对象,然后为将输出文件的文件名配置为一个 output.filename

    module.exports = {
        output:{
            filename:'bundle.js'
        }
    }
    // 此配置将一个单独的 bundle.js 文件输出到dist 目录中
    
  2. 多个入口起点:如果配置中多于一个“chunk”,则应该使用占位符(substitutions)来确保每个文件具有唯一的名称。

    module.exports = {
        entty:{
            app:'./src/app.js',
            search:'./src/search.js'
        },
        output:{
            filename:'[name].js',
            path:__dirname + '/dist'
        }
    }
    // 写入到硬盘:./dist/app.js , ./dist/search.js
    
  3. 高级进阶

loader

webpack只能理解JavaScript 和JSON文件,这是webpack开箱可用的自带能力。loader让webpack能够去处理其他类型的文件,并将他们转换为有效的模块,以供应用程序使用,以及被添加到依赖图中。

在webpack的配置中,loader有两个属性:

  • test 属性,识别哪些文件会被转换

  • use 属性,定义出在进行转换时,应该使用哪个loader

    const path = require('path')
    module.exports = {
        output:{
            filename:'bundle.js'
        }
        module:{
            rules:[{test:/\.txt$/,use:'raw-loader'}]
        }
    }
    

插件(plugin)

loader用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量。

想要使用一个插件,我们只需要require()它,然后把它添加到plugins数组中。多数插件可以通过选项(option)自定义。我们也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用new 操作符来创建一个插件实力。

const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack'); // 用于访问内置插件
module.exports = {
    module:{
        rules:[{test:/\.txt$/,use:'raw-loader'}]
    },
    plugins:[new HtmlWebpackPlugin({template: './src/index.html'})]
}
// html-webpack-plugin 为应用程序生成一个HTML文件,并自动将生成的所有bundle注入到此文件中

模式(mode)

通过选择 development,production或none 之中的一个,来设置mode参数,我们可以启用webpack内置在相应环境下的优化。默认值为production。

module.exports = {
    mode:'production'
}

浏览器兼容性(browser compatibility)

webpack支持所有符合ES5标准的浏览器(不支持IE8及以下版本)。webpack的import()和require.ensure()需要promise。如果我们想要支持旧版本浏览器,在使用这些表达式之前,还需要提前加载polyfillnpm install --save babel-polyfill

然后使用 import 将其引入到我们的文件中。 import 'babel-polyfill'