美文网首页我爱编程
webpack配置及使用

webpack配置及使用

作者: JarvanZ | 来源:发表于2018-03-29 23:58 被阅读0次

概念

本质上,webpack是一个现代javascript应用程序的静态模块打包器(module bundler).当webpack处理应用程序时,它会递归地构建一个依赖关系图,其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个bundle.
主要有四个核心概念:

  • 入口retry
  • 输出output
  • loader
  • 插件plugins
入口(retry)

入口起点(retry point)指示webpack应该使用哪个模块来作为构建其内部依赖图的开始.进入入口起点后,webpack会找出有哪些模块和库是入口起点(直接和间接)依赖的.每个依赖项随机被处理,最后输出到称之为bundles的文件中.

  • 单个入口语法(字符串形式)
const config = {
  entry: './path/to/my/entry/file.js'
};
module.exports = config;
相当于
const config = {
  entry: {
    main: './path/to/my/entry/file.js'
  }
};

当向entry传递一个数组时,将创建"多个主入口".在需要多个依赖文件一起注入,并且将它们的依赖导向到一个"chunk"时.

  • 对象语法
const config = {
  entry: {
    app: './src/app.js',
    vendors: './src/vendors.js'
  }
};

对象语法是应用程序中定义入口的最可拓展的方式.

  • 常见场景
    分离 应用程序(app) 和 第三方库(vendor) 入口.
    这种方式比较常见于只有一个入口起点(不包括vendor)的单页应用程序(spa)中.此设置允许你使用CommonsChunkPlugin从[应用程序bundle]中提取vendor
    引用(vendor reference)到vendor bundle.
  • 多页面应用程序
const config = {
  entry: {
    pageOne: './src/pageOne/index.js',
    pageTwo: './src/pageTwo/index.js',
    pageThree: './src/pageThree/index.js'
  }
};

这是告诉webpack需要3个独立分离的依赖图

输出(output)

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

  • 用法
    最低要求是将输出的值设置为一个对象,包括以下两个属性
    filename用于输出文件的文件名
    目标输出目录path的绝对路径
  • 多个入口起点
    如果配置了创建了多个单独的"chunk",则应该使用占位符来确保每个文件具有唯一的名称
{
  entry: {
    app: './src/app.js',
    search: './src/search.js'
  },
  output: {
    filename: '[name].js',
    path: __dirname + '/dist'
  }
}
  • 高级进阶
output: {
  path: "/home/proj/cdn/assets/[hash]",
  publicPath: "http://cdn.example.com/assets/[hash]/"
}

在编译时不知道最终输出文件的 publicPath 的情况下,publicPath 可以留空,并且在入口起点文件运行时动态设置.如果你在编译时不知道 publicPath,你可以先忽略它,并且在入口起点设置__webpack_public_path__

loader

loader用于对模块的源代码进行转换.loader可以使你在import或"加载"模块时预处理文件.因此,loader类似于其它构建工具中的"任务(task)",并提供了处理前端构建步骤的强大方法.

  • 使用loader
    • 配置(推荐): 在webpack.config.js文件中指定loader
    • 内联: 在每个import语句中显示指定loader
    • CLI: 在shell命令中指定它们
  • 配置[Configuration]
    module.rules荀彧你在webpack设置中指定多个loader.
  • 内联
    可以在import语句或任何等效于"import"的方式中指定loader.使用!将资源中的loader分开
import Styles from 'style-loader!css-loader?modules!./styles.css';

通过前置所有规则以及使用!,可以对应覆盖到配置的任意loader

  • CLI
webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'

这会对 .jade 文件使用 jade-loader,对 .css 文件使用 style-loadercss-loader

  • loader特新
    • 支持链式传递,能够对资源使用流水线
    • 可以是同步的,也可以是异步的
    • 运行在node.js中,并且能够执行任何可能的操作
    • 接受查询参数,用于传递配置
    • 也能够使用options对象进行配置
    • 处理使用package.json常见的main属性,可以将普通的npm模块导出为loader,做法是在package.json中定义一个loader字段
    • 插件可以为loader带来更多特性
    • loader能够产生额外的任意文件
  • 解析loader
    loader遵循标准的模块解析,多数情况下,loader将从模块路径解析.
    loader模块需要导出为一个函数,并且使用Node.js兼容的JavaScript编写.通常使用npm进行管理,但是也可以将自定义loader作为应用程序中的文件
插件(Plugins)

webpack的支柱功能,其自身也是构建于你在webpack配置中用到的相同的插件系统之上
插件目的在于解决与loader无法实现的其他事

  • 剖析
    webpack插件是一个具有apply属性的JavaScript对象.apply属性会被webpack compiler调用,并且compiler对象可在整个编译声明周期访问
  • 用法
    由于插件可以携带参数/选项,你必须在webpack配置中,向plugins属性传入new实例
  • 配置
plugins: [
    new webpack.optimize.UglifyJsPlugin(),
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
  • Node API
    即便使用Node API,用户也应该在配置中传入plugins属性.webpack compiler并不是推荐的使用方式
some-node-script.js

const webpack = require('webpack'); //访问 webpack 运行时(runtime)
  const configuration = require('./webpack.config.js');

  let compiler = webpack(configuration);
  compiler.apply(new webpack.ProgressPlugin());

  compiler.run(function(err, stats) {
    // ...
  });
配置

webpack配置是标准的Node.js CommonJS模块:

  • 通过require(...)导入其他文件
  • 通过require(...)使用npm的工具函数
  • 使用JavaScript控制流表达式,例如三元表达式
  • 对常用值使用常量或变量
  • 编写并执行函数来生成部分配置
模块

在模块化编程中,开发者将程序分解成离散功能块,并称之为模块

  • 什么是webpack模块
    对比Node.js模块,webpack模块能够以各种方式表达它们的依赖关系
    • ES2015import语句
    • CommonJSrequire()语句
    • AMDdefinerequire语句
    • css/sass/less文件中的@import语句
    • 样式(url(...))或html文件(<img src=...>)中的图片链接
  • 支持的模块类型
    webpack通过loader可以支持各种语句和预处理器编写模块.loader描述了webpack如何处理 非JavaScript模块,并且在bundle中引入这些依赖
模块解析

resolver是一个库,用于帮助找到模块的绝对路径.一个模块可以作为另一个模块的依赖模块,然后被后者引用.当打包模块时,webpack使用enhanced-resolve来解析文件路径

  • webpack中的解析规则
    使用enhanced-resolve,webpack能够解析三种文件路径
    1 绝对路径
    2 相对路径
    这种情况下,使用importrequire的资源文件所在的目录认为是上下文目录.在import/require中给定的相对路径会添加上下文路径来产生模块的绝对路径
    3 模块路径
    模块将在resolve.modules中指定的所有目录内搜索.可以使用resolve.alias配置选项来创建一个别名.
    一旦根据上述规则解析路径后,解析器(resolve)将检查路径是否指向文件或目录.
    如果路径指向一个文件:

    • 如果路径具有文件拓展名,则被直接打包
    • 否则,将使用resolve.extensions选项作为文件拓展名来解析(接受哪些拓展名)

    如果路径指向一个文件夹:

    • 如果文件夹包含package.json文件,则按照顺序查找resolve.mainFiles配置选项中指定的字段.并且package.json中的第一个这样的字段确定文件路径.
    • 如果package.json文件不存在或者文件中的main字段没有返回一个有效路径,则按照顺序查找resolve.mainFiles配置选项中指定的文件名,看是否能在import/require目录下匹配到一个存在的文件名
    • 文件拓展名通过resolve.extensions选择采用类似的方法进行解析

webpack根据构建目标为这些选项提供了合理的默认配置

构建目标

因为服务器和浏览器代码都可以使用JavaScript编写,所以webpack提供了多种构建目标.

  • 用法
    只需要在webpack配置中设置target的值
module.exports = {
  target: 'node'
};

这个例子中,使用nodewebpack会编译为用于[类 Node.js]环境(使用Node.js的require,而不是使用任意内置模块(如fspath)来加载chunk)

  • 多个Target
    尽管webpack不支持向target传入多个字符串,但是可以通过打包两份分离的配置来创建同构的库
var path = require('path');
var serverConfig = {
  target: 'node',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'lib.node.js'
  }
  //…
};

var clientConfig = {
  target: 'web', // <=== 默认是 'web',可省略
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'lib.js'
  }
  //…
};

module.exports = [ serverConfig, clientConfig ];

这个例子会在dist文件夹下创建lib.jslib.node.js文件

Manifest

使用webpack构建的典型应用程序或站点中,有三种主要的代码类型

  1. 编写的源码
  2. 源码依赖的任何第三方的library或vendor代码
  3. webpack的runtime和manifest,管理所有模块的交互
  • Runtime
    包含:在模块交互时,连接模块所需的加载和解析逻辑.包括浏览器中的已加载模块的连接以及懒加载模块的执行逻辑
  • Manifest
    当编译器开始执行,解析和映射应用程序时,它会保留所有模块的详细要点,这个数据集合成为"Manifest",当完成打包发送到浏览器时,会在运行时通过Manifest来解析和加载模块.无论选择哪种模块语法,那些语句现在都已经转换为__webpack_require__方法,此方法指向模块标识符.通过使用manifest中的数据,runtime将能够查询模块标识符,检索出背后对应的模块.
模块热替换

在应用程序运行过程中替换,添加或删除模块,而无需重新加载整个页面.主要通过以下几种方式:

  1. 保留在完全重新加载页面时丢失的应用程序状态
  2. 只更新变更内容,以节省宝贵的开发时间
  3. 调整样式更加快速

相关文章

网友评论

    本文标题:webpack配置及使用

    本文链接:https://www.haomeiwen.com/subject/jxxbcftx.html