webpack(2)——配置项详解

引子

昨天有关 Webpack 笔记也是有许多人喜好的,因此今天再接再砺汇总了第二篇笔记,欢迎各位指点不足之处。
以后的笔记应该会记录一些实际开发了,但愿在这个周末内完全入门 Webapckcss

  1. webpack (1)——核心概念的理解
  2. webpack(2)——配置项详解
  3. ...

1. mode

mode 配置项是 webpack4 新增的配置项,这个配置项是必须的。html

若是使用的不是 webpack4 ,该配置项了解一下便可,使用了 webpack4 以上版本,也能够了解一下便可。
事实上它并不是必须的,可是若是忽略它, webpack 会有个警告。vue

该配置项的属性值类型是 String,并有三个可选项:node

  • production
  • development
  • none

1.1 production 默认值

production 默认值会给你提供一系列有效的默认值以便部署你的应用,它注重:react

  • 小的输出体积
  • 运行快速的代码
  • 忽略仅在开发时须要的代码
  • 不暴露源码和文件路径
  • 易于使用的输出产物

1.2 development 默认值

该默认顾名思义是注重最好的开发体验,它注重:jquery

  • 浏览器调试工具
  • 快速开发周期中的快速增量编译
  • 在运行过程当中提供有效的错误信息

当人对于初学者来讲,对于 webpack 的优化还有一段距离,首先咱们大致了解一下便可。webpack

它还有不少其余的优化默认值,可是效果可能并不美好,由于它针对的某些特定的大型项目,而咱们只是入门,因此了解便可。web

2. Module

module 中配置处理模块的规则。正则表达式

2.1 配置 Loader

rules 配置模块的读取和解析规则,一般用来配置 Loader。其类型是一个数组,数组里每一项都描述了如何去处理部分文件。配置一项 rules 时大体可经过如下方式来实现:npm

  1. 条件匹配:经过 testincludeexclude 三个配置项来命中 Loader 要应用规则的文件。
  2. 应用规则:对选中后的文件经过 use 配置项来应用 Loader,能够只应用一个 Loader 或者按照从后往前的顺序应用一组 Loader,同时还能够分别给 Loader 传入参数。
  3. 重置顺序:一组 Loader 的执行顺序默认是 从右到左 执行,经过 enforce 选项可让其中一个 Loader 的执行顺序放到最前或者最后。
module: {
  rules: [
    {
      // 命中 JavaScript 文件
      test: /\.js$/,
      // 用 babel-loader 转换 JavaScript 文件
      // ?cacheDirectory 表示传给 babel-loader 的参数,用于缓存 babel 编译结果加快从新编译速度
      use: ['babel-loader?cacheDirectory'],
      // 只命中src目录里的js文件,加快 Webpack 搜索速度
      include: path.resolve(__dirname, 'src')
    },
    {
      // 命中 SCSS 文件
      test: /\.scss$/,
      // 使用一组 Loader 去处理 SCSS 文件。
      // 处理顺序为从后到前,即先交给 sass-loader 处理,再把结果交给 css-loader 最后再给 style-loader。
      use: ['style-loader', 'css-loader', 'sass-loader'],
      // 排除 node_modules 目录下的文件
      exclude: path.resolve(__dirname, 'node_modules'),
    },
    {
      // 对非文本文件采用 file-loader 加载
      test: /\.(gif|png|jpe?g|eot|woff|ttf|svg|pdf)$/,
      use: ['file-loader'],
    },
  ]
}
复制代码

上面的例子基本将配置 loader 的大部分配置项都涵盖了,很是清晰简洁。

// 使用一组 Loader 去处理 SCSS 文件。
// 处理顺序为从后到前,即先交给 sass-loader 处理,再把结果交给 css-loader 最后再给 style-loader。
use: ['style-loader', 'css-loader', 'sass-loader']
复制代码

在上面的例子中,对于多 Loader 处理方式中,采用的是数组,执行数序为从左到右

除此以外,咱们还能够经过一个 Object 方式来写这一块的代码

use: [
  {
    loader:'babel-loader',
    options:{
      cacheDirectory:true,
    },
    // enforce:'post' 的含义是把该 Loader 的执行顺序放到最后
    // enforce 的值还能够是 pre,表明把 Loader 的执行顺序放到最前面
    enforce:'post'
  },
  // 省略其它 Loader
]
复制代码

对于 Loader 的最后一点补充就是关于命中文件的三个配置项:textincludeexclude

在上述例子中,这三兄弟的配置只传入了一个字符串或者是正则,其实他们还均可以支持数组,数组之间的关系为 “或”的关系,即文件知足数组中的任何一个条件,都会被命中。

2.2 noParse

noParse 配置项可让 Webpack 忽略对部分没采用模块化的文件的递归解析和处理,这样作的好处是能提升构建性能。 缘由是一些库例如 jQueryChartJS 它们庞大又没有采用模块化标准,让 Webpack 去解析这些文件耗时又没有意义。

noParse 是可选配置项,类型须要是 RegExp、[RegExp]、function 其中一个。

// 使用正则表达式
noParse: /jquery|chartjs/

// 使用函数,从 Webpack 3.0.0 开始支持
noParse: (content)=> {
  // content 表明一个模块的文件路径
  // 返回 true or false
  return /jquery|chartjs/.test(content);
}
复制代码

注意被忽略掉的文件里不该该包含 import 、 require 、 define 等模块化语句,否则会致使构建出的代码中包含没法在浏览器环境下执行的模块化语句。

2.3 parse

由于 Webpack 是以模块化的 JavaScript 文件为入口,因此内置了对模块化 JavaScript 的解析功能,支持 AMD、CommonJS、SystemJS、ES6。 parser 属性能够更细粒度的配置哪些模块语法要解析哪些不解析,和 noParse 配置项的区别在于 parser 能够精确到语法层面, 而 noParse 只能控制哪些文件不被解析。 parser 使用以下:

module: {
  rules: [
    {
      test: /\.js$/,
      use: ['babel-loader'],
      parser: {
      amd: false, // 禁用 AMD
      commonjs: false, // 禁用 CommonJS
      system: false, // 禁用 SystemJS
      harmony: false, // 禁用 ES6 import/export
      requireInclude: false, // 禁用 require.include
      requireEnsure: false, // 禁用 require.ensure
      requireContext: false, // 禁用 require.context
      browserify: false, // 禁用 browserify
      requireJs: false, // 禁用 requirejs
      }
    },
  ]
}
复制代码

3. Resolve

该配置项主要是配置 Webapck 如何寻找模块所对应的文件。
Webpack 内置 JavaScript 模块化语法解析功能,默认会采用模块化标准里约定好的规则去寻找,但你也能够根据本身的须要修改默认的规则。

该配置项的属性蛮多的,可是我以为我能用获得的也就几个=。=

3.1 alias

resolve.alias 配置项经过别名来把原导入路径映射成一个新的导入路径。例如使用如下配置:

// Webpack alias 配置
resolve:{
  alias:{
    components: './src/components/'
  }
}
复制代码

当你经过 import Button from 'components/button' 导入时,实际上被 alias 等价替换成了 import Button from './src/components/button'

以上 alias 配置的含义是把导入语句里的 components 关键字替换成 ./src/components/

这样作可能会命中太多的导入语句,alias 还支持 $ 符号来缩小范围到只命中以关键字结尾的导入语句:

resolve:{
  alias:{
    'react$': '/path/to/react.min.js'
  }
}
复制代码

react$ 只会命中以 react 结尾的导入语句,即只会把 import 'react' 关键字替换成 import '/path/to/react.min.js'

该方法的应用场景有待我去探索,真不太清楚这样替换的缘由。
可是我以为是蛮有用的。

3.2 extensions

在导入语句没带文件后缀时,Webpack 会自动带上后缀后去尝试访问文件是否存在。 resolve.extensions 用于配置在尝试过程当中用到的后缀列表,默认是:

extensions: ['.js', '.json']

这个配置项应该有用,在处理 TypeScriptvue 这些文件的时候,能够设置一下

3.3 enforceExtension

resolve.enforceExtension 若是配置为 true 全部导入语句都必需要带文件后缀, 例如开启前 import './foo' 能正常工做,开启后就必须写成* import './foo.js'。*

对于 Resolve 的其余配置项,大致了解一下便可,我以为可能用的不是特别多。

3.4 Plugins

对于 Plugins 的使用,上一节也写到过,仍是那句话吧:

使用 Plugin 的难点在于掌握 Plugin 自己提供的配置项,而不是如何在 Webpack 中接入 Plugin。

4. DevServer

使用 DevServer 能干啥?

  • 提供 HTTP 服务来预览本地文件;
  • 监听文件的变化并自动刷新页面;
  • 支持 Source Map,以方便调试。

DevServer 会启动一个 HTTP 服务器 用于服务网页请求,同时会帮助启动 Webpack,并接收 Webpack 发出的文件更新信号,经过 webSocket 协议自动刷新网页作到实时预览。

4.1 开启一个DevServer 服务

集成 DevServer ,首先须要安装一下:

npm i -D webpack-dev-server
复制代码

若是不是经过 npm run 启动,直接将 webpack-dev-server 安装到全局,直接使用,会报: webpack-dev-server: command not found

安装成功后,执行 webpack-dev-server 命令,接着一连串日志输出:

i 「wds」: Project is running at http://localhost:8080/
i 「wds」: webpack output is served from /
i 「wdm」: Hash: 5cece8a0d7243a4cf1ba
Version: webpack 4.8.3
Time: 1627ms
Built at: 2018-05-18 14:18:57

......
复制代码

4.2 ./dist/bundle.js 加载 404 问题

用浏览器直接打开这个地址你会发现页面空白,错误缘由是 ./dist/bundle.js 加载404了。 同时你会发现并无文件输出到 dist 目录,缘由是 DevServer 会把 Webpack 构建出的文件保存在内存中,在要访问输出的文件时,必须经过 HTTP 服务访问。 因为 DevServer 不会理会 webpack.config.js 里配置的 output.path 属性,因此要获取 bundle.js 的正确 URLhttp://localhost:8080/bundle.js

4.3 实时预览

webpack --watch 会开启监听模式,而 webpack 启动默认是关闭的,开启 DevServer 默认开启监听模式,因此修改须要被打包的文件浏览器会被自动刷新,这里主要应用到了 Websocket ,有须要的童鞋能够去了解一下。

4.4 修改index.html并不会被刷新的缘由

若是尝试修改 index.html 文件并保存,你会发现这并不会触发以上机制,致使这个问题的缘由是 Webpack 在启动时会以配置里的 entry 为入口去递归解析出 entry 所依赖的文件,只有 entry 自己和依赖的文件才会被 Webpack 添加到监听列表里。 而 index.html 文件是脱离了 JavaScript 模块化系统的,因此 Webpack 不知道它的存在。

能够尝试用 raw-loader 来处理一下 html

4.5 热更新 --hot

固然上述实现页面更改都是基于页面刷新实现的,DevServer 还有一种被称做模块热替换的刷新技术——热更新。

DevServer 默认是关闭热更新的,能够经过

webpack-dev-server --hot
复制代码

来开启

4.6 Source Map

webpack-dev-server --devtool source-map
复制代码

这个功能就很少说了。

4.7 devserver 配置项

plugins: [
    new webpack.HotModuleReplacementPlugin()
],
devServer: {
    hot: true,
    open: 'http://127.0.0.1:9000',
    // inline: true,
    // contentBase: path.join(__dirname, "dist"),
    compress: true,
    port: 9000
}
复制代码

devServer 的配置项也是蛮多的,看了很久,发现有用的也就是这几个吧:

  • hot: 开启热更新;
  • open:自动打开要开发的网页;
  • inline:实时预览功能,即页面刷新,用热更新替代便可,不必管他;
  • compress: 开启 Gzip 压缩;
  • port:服务器监听的端口号,指定便可,若是不指定,默认是 8080 ,冲突了会自动顺位 808一、8082,挺赞的。

该配置项还有不少其余的属性,我以为目前我是用不上,但不妨碍咱们了解一下,在此我就不一一记录了。

写在最后

webpack 的基本操做到目前为止基本结束,他能完成的功能仍是有不少的,从它的 N 多配置项就能看出来,但咱们不须要所有记住,记住以前的核心概念和它的基本原理就能够,以后再根据本身的经验去判断它属于哪一块再去查文档就没问题。

  • 让源文件加入到构建流程中去被 Webpack 控制,配置 entry。
  • 自定义输出文件的位置和名称,配置 output。
  • 自定义寻找依赖模块时的策略,配置 resolve。
  • 自定义解析和转换文件的策略,配置 module,一般是配置 module.rules 里的 Loader。
  • 其它的大部分需求可能要经过 Plugin 去实现,配置 plugin。

参考

webpack4:模式与优化
深刻浅出 Webpack
webpack 配置项
[HMR] Hot Module Replacement is disabled
Gzip

相关文章
相关标签/搜索