好啦, 介绍完 webpack 到底是干什么的以后呢, 我们需要进入正题了, 这篇主要介绍 webpack 的几个重要的概念入口, 出口, loader, 插件 plugins, 模式
入口(entry point)
指示 webpack 应该使用哪个模块, 来作为构建其内部依赖图的开始. 进入入口起点后, webpack 会找出有哪些模块和库是入口起点 (直接和间接) 依赖的. 每个依赖项随即被处理, 最后输出到称之为 bundles 的文件中,
可以通过在 webpack 配置中配置 entry 属性, 来指定一个入口起点(或多个入口起点). 默认值为 ./src.
接下来我们看一个 entry 配置的最简单例子:
webpack.config.JS
- module.exports = {
- entry: './path/to/my/entry/file.js'
- };
单个入口语法
webpack.config.JS
- const config = {
- entry: './path/to/my/entry/file.js' // 此写法是下面的写法简写
- <!-- entry: {
- main: './path/to/my/entry/file.js'
- } -->
- };
- module.exports = config;
当你向 entry 传入一个数组时会发生什么? 向 entry 属性传入「文件路径 (file path) 数组」将创建 "多个主入口 (multi-main entry)". 在你想要多个依赖文件一起注入, 并且将它们的依赖导向(graph) 到一个 "chunk" 时, 传入数组的方式就很有用.
对象语法
webpack.config.JS
- const config = {
- entry: {
- App: './src/app.js',
- vendors: './src/vendors.js'
- }
- };
对象语法会比较繁琐. 然而, 这是应用程序中定义入口的最可扩展的方式.
数组语法
webpack.config.JS
- const config = {
- entry: ['./src/app.js','./src/vendors.js']
- };
总结: 上面关于对象和数组语法主要是面向多页面应用 (MPA) 的, 在多页应用中,(译注: 每当页面跳转时)服务器将为你获取一个新的 html 文档. 页面重新加载新文档, 并且资源被重新下载. 然而, 这给了我们特殊的机会去做很多事: 使用 CommonsChunkPlugin(该插件主要作用就是通过将公共模块拆出来 - 多个入口情况下, 最终合成的文件能够在最开始的时候加载一次) 为每个页面间的应用程序共享代码创建 bundle. 由于入口起点增多, 多页应用能够复用入口起点之间的大量代码 / 模块, 从而可以极大地从这些技术中受益.
出口(output)
output 属性告诉 webpack 在哪里输出它所创建的 bundles, 以及如何命名这些文件, 默认值为 ./dist. 基本上, 整个应用程序结构, 都会被编译到你指定的输出路径的文件夹中. 你可以通过在配置中指定一个 output 字段, 来配置这些处理过程:
webpack.config.JS
- const path = require('path');
- module.exports = {
- entry: './path/to/my/entry/file.js',
- output: {
- path: path.resolve(__dirname, 'dist'), // 输出的路径, 结合 node 的 path 模块
- filename: 'my-first-webpack.bundle.js' // 输出的文件名
- }
- };
- output.filename
这里单独说一下 filename 其他用法
此选项决定了每个输出 bundle 的名称. 这些 bundle 将写入到 output.path 选项指定的目录下.
对于单个入口起点, filename 会是一个静态名称.
filename: "bundle.js"
然而, 当通过多个入口起点 (entry point), 代码拆分(code splitting) 或各种插件 (plugin) 创建多个 bundle, 应该使用以下一种替换方式, 来赋予每个 bundle 一个唯一的名称......
使用入口名称:
filename: "[name].bundle.js"
使用内部 chunk id
filename: "[id].bundle.js"
使用每次构建过程中, 唯一的 hash 生成, 可以指定 hash 生成的长度如:[hash:8]
filename: "[name].[hash].bundle.js"
使用基于每个 chunk 内容的 hash:
filename: "[chunkhash].bundle.js"
因为 hash 是项目构建的哈希值, 项目中如果有些变动, hash 一定会变, 比如说我改动了 utils.JS 的代码, index.JS 里的代码虽然没有改变, 但是大家都是用的同一份 hash.hash 一变, 缓存一定失效了, 这样子是没办法实现 CDN 和浏览器缓存的.
其他配置项
总结: 上面是 webpack 的最基础的配置, 输入和输出, 当然这里引入了一个 chunk 的概念, chunk 表示一个文件, 默认情况下 webpack 的输入是一个入口文件, 输出也是一个文件, 这个文件就是一个 chunk,chunkId 就是产出时给每个文件一个唯一标识 id,chunkhash 就是文件内容的 md5 值, name 就是在 entry 中指定的 key 值.
- module.exports = {
- entry: {
- collection: './src/main.js' // collection 为 chunk 的名字, chunk 的入口文件是 main.JS
- },
- output: {
- path: './dist/js',
- filename: '[name].[chunkhash].[hash:8].js' // 输出到 dist/JS 目录下, 以 collection+chunk 内容的 md5 值作为输出的文件名
- }
- };
以上输入输出会出现几个概念, 下面做一下总结:
- entry:{
- main:['./src/main.js','./src/test.js'],
- other:['./src.other.js']
- },
- output:{
- filename:"[name].bundle.js"
- }
main.JS 中引入了 gloabl.CSS;
module
main.JS,test.JS,other.JS,global.CSS 都是 module
- entry-point
- main.JS,test.JS,other.JS
- chunk
- main
- other
- bundle
main.bundle.JS
other.bundle.JS
entry 的两个 key 对应两个 chunk, 最终会输出两个 bundle;main.JS,test.JS,other.JS 都是 entry-point
loader
loader 让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript).loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块, 然后你就可以利用 webpack 的打包能力, 对它们进行处理.
本质上, webpack loader 将所有类型的文件, 转换为应用程序的依赖图 (和最终的 bundle) 可以直接引用的模块.
在更高层面, 在 webpack 的配置中 loader 有两个目标:
test 属性, 用于标识出应该被对应的 loader 进行转换的某个或某些文件.
use 属性, 表示进行转换时, 应该使用哪个 loader.
webpack.config.JS
- const path = require('path');
- const config = {
- output: {
- filename: 'my-first-webpack.bundle.js'
- },
- module: {
- rules: [
- { test: /\.txt$/, use: 'raw-loader' }
- ]
- }
- };
- module.exports = config;
以上配置中, 对一个单独的 module 对象定义了 rules 属性, 里面包含两个必须属性: test 和 use. 这告诉 webpack 编译器(compiler) 如下信息:
"嘿, webpack 编译器, 当你碰到「在 require()/import 语句中被解析为'.txt'的路径」时, 在你对它打包之前, 先使用 raw-loader 转换一下."
重要的是要记得, 在 webpack 配置中定义 loader 时, 要定义在 module.rules 中, 而不是 rules. 然而, 在定义错误时 webpack 会给出严重的警告. 为了使你受益于此, 如果没有按照正确方式去做, webpack 会 "给出严重的警告"
插件(plugins)
loader 被用于转换某些类型的模块, 而插件则可以用于执行范围更广的任务. 插件的范围包括, 从打包优化和压缩, 一直到重新定义环境中的变量. 插件接口功能极其强大, 可以用来处理各种各样的任务.
想要使用一个插件, 你只需要 require() 它, 然后把它添加到 plugins 数组中. 多数插件可以通过选项 (option) 自定义. 你也可以在一个配置文件中因为不同目的而多次使用同一个插件, 这时需要通过使用 new 操作符来创建它的一个实例.
webpack.config.JS
- const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 NPM 安装
- const webpack = require('webpack'); // 用于访问内置插件
- const config = {
- module: {
- rules: [
- { test: /\.txt$/, use: 'raw-loader' }
- ]
- },
- plugins: [
- new HtmlWebpackPlugin({template: './src/index.html'})
- ]
- };
- module.exports = config;
webpack 提供许多开箱可用的插件! 查阅我们的插件列表获取更多信息.
模式
通过选择 development 或 production 之中的一个, 来设置 mode 参数, 你可以启用相应模式下的 webpack 内置的优化
- module.exports = {
- mode: 'production'
- };
或
webpack --mode=production
选项 | 描述 |
---|---|
development | 会将 process.env.NODE_ENV 的值设为 development。启用 NamedChunksPlugin 和 NamedModulesPlugin。 |
production | 会将 process.env.NODE_ENV 的值设为 production。启用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 UglifyJsPlugin. |
来源: http://www.jianshu.com/p/16c591af500e