webpack学习笔记

学webpack是因为每次写错代码之后的调试都会因为代码被压缩过而找不到出错的原始位置,所以想学一学到底怎么配置。

Webpack 文档学习

概念

Webpack

是什么

  • webpack是一个静态模块打包器

实现方法

  • 在内部创建一个依赖图,用于映射到项目需要的每个模块
  • 将这些依赖生成到一个或多个bundle

核心概念

  • 入口
  • 输出
  • loader
  • 插件

入口「entry」

是什么

  • 指示webpack应该使用哪个模块来作为构建其内部依赖图的开始
  • webpack会找出有哪些模块和library是入口起点(直接和间接)依赖的
  • 默认值是./src/index.js

如何配置

单个入口
  • 用法:entry: string|Array<string>

  • webpack.config.js

    1
    2
    3
    module.exports = {
    entry: './path/to/my/entry/file.js'
    }
  • 单个入口写法:

    1
    2
    3
    4
    5
    module.exports = {
    entry: {
    main: './path/to/my/entry/file.js'
    }
    }
对象语法
  • 用法:entry: {[entryChunkName: string]: string|Array<string>}

  • webpack.config.js

    1
    2
    3
    4
    5
    6
    module.exports = {
    entry: {
    app: './src/app.js',
    vendors: './src/vendors.js'
    }
    }
经验

一个HTML页面只指定一个入口

出口

是什么

  • 告诉webpack在哪里输出它所创建的bundles,以及如何命名这些文件(控制webpack如何向硬盘写入编译文件)

  • 主输出文件默认为./dist/main.js

  • 其他生成文件默认输出目录是./dist

  • 即使可以存在多个入口,但只指定一个输出配置

用法

  • 将它的值设置为一个对象

  • filename用于输出文件的文件名

  • 模板输出目录path的绝对路径

    1
    2
    3
    4
    5
    6
    module.exports = {
    output: {
    filename: 'bundle.js',
    path: '/home/proj/public/assets'
    }
    }

模式「mode」

是什么

  • mode参数设置为developmentproductionnone可以启用对应环境下webpack内置的优化

  • 默认值为production

用法

  • 配置中提供

    1
    2
    3
    module.exports = {
    mode: 'production'
    }
  • 命令行工具传入

    1
    webpack --mode=production

三种模式的区别

development
  • 会将process.env.NODE_ENV的值设为development

  • 启用NamedChunksPluginNamedModulesPlugin

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    //webpack.development.config.js
    module.exports = {
    mode: 'development'
    plugins: [
    new webpack.NamedModulesPlugin(),
    new webpack.NamedChunksPlugin(),
    new webpack.DefinePlugin({
    "process.env.NODE_ENV": JSON.stringify("development")
    })
    ]
    }
production
  • 会将process.env.NODE_ENV的值设为production

  • 启用FlagDependencyUsagePlugin, FLagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurenceOrderPlugin, SideEffectsFlagPlugin, UglifyJsPlugin

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //webpack.production.config.js
    module.exports = {
    mode: 'production',
    plugins: [
    new UglifyJsPlugin(/* ... */),
    new webpack.DefinePlugin({
    "process.env.NODE_ENV": JSON.stringify("production")
    }),
    new webpack.optimize.ModuleConcatenationPlugin(),
    new webpack.NoEmitOnErrorsPlugin()
    ]
    }

loader

是什么

  • loader让webpack处理非javascript文件
  • 先将这些文件转换为有效模块,然后添加到依赖图中

两大特征

  • test属性
    • 用于表示出应该被对应的loader进行转换的某个或某些文件
  • use属性
    • 进行转换时,应该使用哪个loader

使用方法

  • 先安装对应的loader

    1
    2
    npm install --save-dev css-loader
    npm install --save-dev ts-loader
  • 指示给对应类型的文件使用对应loader

    1
    2
    3
    4
    5
    6
    7
    8
    module.exports = {
    module: {
    rules: [
    {test: /\.css$/, use: 'css-loader'},
    {test: /\.ts$/, use: 'ts-loader'}
    ]
    }
    }
  • 允许使用多个loader

使用方式
  1. 配置: 在webpack.config.js中指定loader
  2. 内联: 在每个import语句中显式指定loader
  3. CLI: 在shell命令中指定它们

插件

是什么

  • 用于打包优化、资源管理、注入环境变量
  • 是一个有apply方法的JS对象

使用方法

  • 先在配置文件中require()
  • 将它添加到plugins数组中

配置

devtool

  • 控制是否生成以及如何生成source map
devtool 构件速度 重新构建速度 生成环境 代码形式
(none) +++ +++ yes 打包后的代码
Eval +++ +++ no 生成后的代码
cheap-eval-source-map + ++ no 转换过的代码(仅限行)
cheap-module-eval-source-map o ++ no 原始源代码(仅限行)
eval-source-map + no 原始源代码
cheap-source-map + o yes 转换过的代码(仅限行)
cheap-module-source-map o - yes 原始源代码(仅限行)
inline-cheap-source-map + o no 转换过的代码(仅限行)
inline-cheap-module-source-map o - no 原始源代码(仅限行)
source-map yes 原始源代码
inline-source-map no 原始源代码
hidden-source-map yes 原始源代码
nosources-source-map yes 无源代码内容
概念辨析
  • 打包后的代码:将所有生成的代码视为一大块代码,看不到相互分离的模块
  • 生成后的代码:每个模块相互分离,并用模块名称进行注释;可以看到webpack生成的代码
  • 转换过的代码:每个模块相互分离,并用模块名称进行注射;可以看到webpack转换前、loader转译后的代码
  • 原始源代码:每个模块相互分离,并用模块名称进行注释;可以看到转译之前的代码,正如编写它时那样
  • 无源代码内容:source map中不包含源代码内容,浏览器通常会尝试从web服务器或文件系统加在源代码
  • (仅限行):source map会简化为每行一个映射,通常意味着每个语句只有一个映射