webpack配置及使用

概念

本质上,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. 调整样式更加快速
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • 版权声明:本文为博主原创文章,未经博主允许不得转载。 webpack介绍和使用 一、webpack介绍 1、由来 ...
    it筱竹阅读 11,060评论 0 21
  • webpack 介绍 webpack 是什么 为什么引入新的打包工具 webpack 核心思想 webpack 安...
    yxsGert阅读 6,460评论 2 71
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,637评论 18 139
  • GitChat技术杂谈 前言 本文较长,为了节省你的阅读时间,在文前列写作思路如下: 什么是 webpack,它要...
    萧玄辞阅读 12,681评论 7 110
  • 一、概述 本文将简单介绍webpack的基本用途以及它的四个基本概念Entry(入口文件)、Loader(加载器)...
    荣儿飞阅读 749评论 0 1