一 概念javascript
1 入口(entry)css
入口起点(entry point)提示webpack 应该使用那个模块,来做为构建其内部依赖图得开始。进入入口七点后,webpack 会找出那些模块和库是入口起点(直接和间接)依赖的。html
每一项依赖随即被处理,最后输出到称之为bundles的文件中,前端
能够经过webpack配置中的配置entry属性,来指指定一个入口起点(或多个入口起点)。默认值为 ./src。java
webpack.config.文件中node
module.exports = { entry:'./path/to/my/entry/file.js' }
2 出口(output)webpack
output 属性告诉webpack再哪里输出它所建立的bundles,以及如何命名这些文件,默认值为 ./dist。基本上,整个应用程序结构,都会被编译到你指定的输出路径的文件夹中,你能够经过再配置中指定一个output字段,来配置这些处理过程:git
webpack.config.jsgithub
const path = require('path'); module.exports = { entry :'./path/to/my/entry/file.js', output:{ path:path.resolve(_dirname,'dist'), filename:'my_first_webpack.bundle.js' } }
在上面的示例中,咱们经过output.path和output.filename两个属性,来告诉webpack bundle的名称以及咱们想要bundle生成web
(emit)到哪里。可能你想要了解在代码最上面导入的path模块是什么,它是一个node.js的核心模块。用于操做文件路径。
3 loader
loader 让webpack可以处理那些非javascript文件(webpack自身只理解javascript)。loader能够将全部类型的文件转换为webpacck可以处理的有效模块,而后你就能够利用webpack的打包能力,对他们进行处理。
本质上,webpack loader 将全部类型的文件,转化为应用程序的依赖图(和最终的bundle)能够直接引用的模块。
注意 ,loader可以import导入任何类型的模块(例如:.css文件)
在更高层面,在webpack的配置中loader有两个目标:
1 test 属性,用于标识出应该被对应的loader进行转换的某个或某些文件
2 use 属性, 标识进行转换时,应该使用哪个loader
weback.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编译器以下信息:
在require()/import 语句中被解析为'.txt'的路径时,在你对它进行打包以前,先使用raw-loader转换一下。
4 插件(plugins)
loader被用于转换某些类型的模块,而插件则能够用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到从新定义环境变量。插件接口功能及其强大,能够用来处理各类各样的任务。
想要使用一个插件,你只须要require()它,而后把他添加到plugins数组中。多数插件能够经过选项(option)自定义。你也能够在一个配置文件中由于不一样目的而屡次使用同一个插件,这是须要经过使用new操做符来建立他的一个实例。
webpack.config.js
const Htmlwebpackplugin = require('html-webpack-plugin'); const webpack = require('webpack'); const config = { module:{ rules:[ { test : /\.txt$/,use : 'raw-loader' } ] }, plugins:{ new webpack .optimize.UglifyJsPlugin(), new Htmlwebpackplugin({ template: './src/index.html' }) } } module.exports = config;
5 模式
经过选择development或production 之中的一个,来设置mode参数,你能够启用香英的模式下的webpack内置优化
module.export = { mode:'production' }
二 入口起点
1单个入口(简写)语法
用法entry:string|Array<string>
webpack.config.js
const config = { entry :'./path/to/my/entry/file.js' } module.exports = config;
entry 属性的单个入口语法,是下面的简写:
const config = { entry :{ main:'./path/to/my/entry/file.js' } };
注意:
当你向 entry
传入一个数组时会发生什么?
向 entry
属性传入「文件路径(file path)数组」将建立“多个主入口(multi-main entry)”。在你想要多个依赖文件一块儿注入,而且将它们的依赖导向(graph)到一个“chunk”时,传入数组的方式就颇有用。
使用此语法在扩展配置时有失灵活性。
2 对象语法
用法:entry :{ [ entryChunkName:string ] : string|Array<string> }
webpack.config.js
const config = { entry :{ app :'./src/app.js', vendors:'./src/vendors.js' } }
对象语法比较繁琐,然而,这是应用程序中定义入口的最可扩展的方式。
注意:
“可扩展的 webpack 配置”是指,可重用而且能够与其余配置组合使用。这是一种流行的技术,用于将关注点(concern)从环境(environment)、构建目标(build target)、运行时(runtime)中分离。而后使用专门的工具(如 webpack-merge)将它们合并。
3 常见场景
分离应用程序app和第三方库入口
webpack.config.js
const config = { entry :{ app:'./src/app.js', vendors:'./src/wendors.js' } }
这是什么?告诉咱们webpack从app.js 和vendors.js开始建立依赖图,这些依赖图是彼此彻底分离,相互独立的(每个bundle中都有一个webpack引导(bootstrap))。这种方式比较常见于,只有一个入口起点(不包含vendor)的单页应用程序中。
为何?此设置容许你使用CommonsChunkPlugin从应用程序bundle中提取vendor引用到vendor bundle ,而且把引用vendor的部分替换为_webpack_require()调用。若是应用程序bundle中没有vendor代码,那么你能够在webpack中实现被称为长效缓存的通用模式
4 多页面应用程序
webpack.config.js
const config = { entry :{ pageone:'./src/pagone/index.js', pagetwo:'./src/pagetwo/index.js', pagetree:'./src/pagetree/index.js', } }
为何?告诉咱们webpack须要三个独立分离的依赖图
为何?在多页面应用程序中,(每当页面跳转时)服务器将会为你从新获取一个新的html文档,页面从新加载新文档,而且资源从新下载,然而,这给了咱们特殊的机会去作不少事情
使用CommonsChunkPlugin 为每一个页面间的应用程序共享代码建立bundle。因为入口起点增多,多页应用可以服用入口起点之间的大量代码/模块,从而能够极大地从这些技术中受益
三 输出 output
配置output 选项能够控制webpack如何向硬盘写入编译文件。注意即便存在多个入口起点,但只指定一个输出配置。
1 用法
在webpack中配置outpack属性的最低要求是,将它的值设置为一个对象,包括一下两点:
filename:用于输出文件的文件名;
目标输出目录path的绝对路径;
webpack.config.js
const config={ output:{ filename:'bundle.js', path:'./home/proj/public/assets' } } module.export = config;
此配置将一个单独的 bundle.js
文件输出到 /home/proj/public/assets
目录中。
2 多个入口起点
若是配置建立了多个单独得chunk(例如:使用多个入口起点或者使用像CommonChunkPlugin这样得插件),则应该使用占位符来确保每一个文件具备惟一得名称
{ entry: { app: './src/app.js', search: './src/search.js' }, output: { filename: '[name].js', path: __dirname + '/dist' } } // 写入到硬盘:./dist/app.js, ./dist/search.js
3 高级进阶
如下是使用 CDN 和资源 hash 的复杂示例:
config.js
output:{ path: "/home/proj/cdn/assets/[hash]", publicPath: "http://cdn.example.com/assets/[hash]/" }
在编译时不知道最终输出文件的 publicPath
的状况下,publicPath
能够留空,而且在入口起点文件运行时动态设置。若是你在编译时不知道 publicPath
,你能够先忽略它,而且在入口起点设置 __webpack_public_path__
。
__webpack_public_path__ = myRuntimePublicPath // 剩余的应用程序入口
四 模式 mode
提供mode配置选项,告知webpack使用香英模式得内置优化。
string
1 用法
只在配置中提供mode选项:
module.exports = { mode:'production' }
或者从命令中传参
wbpack --mode=production
支持一下字符串
选项 | 描述 |
development | 会将
|
production | 会将
|
// webpack.development.config.js module.exports = { + mode: 'development' - plugins: [ - new webpack.NamedModulesPlugin(), - new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }), - ] }
// 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用于对模块得源代码进行转换。loader可使你在import或‘加载’模块时预处理文件。所以,loader 相似于其实他构建工具中‘任务task’,并提供了处理前端构建步骤得强大方法。loader能够将文件从不一样得语言(如:typeScript)转换成javascript,或将内联图像转换为data url 。loader甚至容许你直接在javascript模块中inport CSS文件!
1 示例
你可使用 loader 告诉 webpack 加载 CSS 文件,或者将 TypeScript 转为 JavaScript。为此,首先安装相对应的 loader:
npm install --save-dev css-loader
npm install --save-dev ts-loader
而后指示 webpack 对每一个 .css
使用 css-loader
,以及对全部 .ts
文件使用 ts-loader:
webpack.config.js
module.exports = { module :{ rules:[ {test:/\.css$/,use:'css-loader'}, {test:/.\ts$/,use:'ts-loader'} ] } }
在你的应用程序中,有三种使用 loader 的方式:
配置:在 webpack.config.js 文件中指定 loader。
内联:在每一个 import
语句中显式指定 loader。
CLI:在 shell 命令中指定它们。
3 配置
module.rules容许你在webpack中指定多个loader。这是展现loader得一种简明方式。而且有助于使代码变得更加简洁,同时让你对各个loader有个全局得概览:
module: { rules: [ { test: /\.css$/, use: [ { loader: 'style-loader' }, { loader: 'css-loader', options: { modules: true } } ] } ] }
4 内联
能够在import语句或者任何等效于 import 语句的方式中指定loader。使用!将资源中的loader分开,分开的每一个部分都至关于当前目录解析,
import Styles from 'style-loader!css-loader?modules!./styles.css';
经过前置全部规则及使用 !。能够对应覆盖到配置中的任意loader。
选项能够传递查询参数,例如 ?key=value&foo=bar
,或者一个 JSON 对象,例如 ?{"key":"value","foo":"bar"}
。
注意 : 尽量使用 module.rules
,由于这样能够减小源码中的代码量,而且能够在出错时,更快地调试和定位 loader 中的问题。
5 CLI
经过CLI来使用loader
webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'
这会对 .jade文件使用 jade-loader 对.css文件使用style-loader和css-loader
6 loader特性
loader 经过(loader)预处理函数,为 JavaScript 生态系统提供了更多能力。 用户如今能够更加灵活地引入细粒度逻辑,例如压缩、打包、语言翻译和其余更多。
7 解析loader
loader 遵循标准的模块解析。多数状况下,loader 将从模块路径(一般将模块路径认为是 npm install
, node_modules
)解析。
loader 模块须要导出为一个函数,而且使用 Node.js 兼容的 JavaScript 编写。一般使用 npm 进行管理,可是也能够将自定义 loader 做为应用程序中的文件。按照约定,loader 一般被命名为 xxx-loader
(例如 json-loader
)
六 插件 plugin
插件得目的用于解决loader没法实现得其余事.
1 剖析
webpack插件是一个具备apply属性得JavaScript对象。apply属性会被webpack compiler 调用,而且comipler对象能够在整个编译生命周期访问。
ConsoleLogOnBuildWebpackPlugin.js
const pluginName = 'ConsoleLogOnBuildWebpackPlugin'; class ConsoleLogOnBuildWebpackPlugin { apply(compiler){ compiler.hook.run.tap(pulginName,compilation =>{ console.log("webpack 构建过程开始!"); }) } }
注意:compiler hook 的 tap 方法的第一个参数,应该是驼峰式命名的插件名称。建议为此使用一个常量,以便它能够在全部 hook 中复用。
2 用法
因为插件能够携带参数/选项,你必须在 webpack 配置中,向 plugins
属性传入 new
实例。
3 配置
webpack.config.js
const config = { entry :'./path/to/my/entry/first.js', output:{ filename:'my-first-webpack.bundle.js', path:path.resolve(_dirname,'dist'), }, module:{ rules:[ { test:/.\(js|jsx)$/, use:'babel-loader' } ] }, plugins:[ new webpack.optimize.UglifyJsPlugin(), new HtmlWebpackPlugin({template:'./src/index.js'}) ] }; module.exports = config;
4 Node API
注意:即使使用 Node API,用户也应该在配置中传入 plugins
属性。compiler.apply
并非推荐的使用方式。
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 的配置文件,是导出一个对象的 JavaScript 文件。此对象,由 webpack 根据对象定义的属性进行解析。
由于 webpack 配置是标准的 Node.js CommonJS 模块,你能够作到如下事情:
require(...)
导入其余文件require(...)
使用 npm 的工具函数?:
操做符请在合适的时机使用这些特性。
虽然技术上可行,但应避免如下作法:
--env
)时,访问命令行接口(CLI)参数1 基本配置
webpack.config.js
var path = require('path'); module.exports = { mode: 'development', entry: './foo.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'foo.bundle.js' } };
八 模块
1 什么是webpack模块?
对比node.js模块,webpack 模块 可以以各类方式表达它们得依赖关系,以下几个例子:
require()
语句。define
和 require
语句。url(...)
)或 HTML 文件(<img src=...>
)中的图片连接(image url)。2 支持模块类型
webpack 经过 loader 能够支持各类语言和预处理器编写模块。loader 描述了 webpack 如何处理 非 JavaScript(non-JavaScript) _模块_,而且在bundle中引入这些_依赖_。 webpack 社区已经为各类流行语言和语言处理器构建了 loader,包括:
九 模块解析
resolver是一个库,用于帮助找到模块得绝对路径。帮助webpack找到bundle中须要引入得模块代码,这些代码在包含在每一个require/import语句中。当打包模块时,webpack使用enhanced-resolve来解析文件路径。
1 webpack中的解析规则
使用enhanced-resolve能够解析三种文件路径:
2 绝对路径
不须要作进一步解析
import "/home/me/file";
import "C:\\User\\me\\file";
3 相对路径
import "../src/file1";
import "./file2"
在这种状况下,使用 import
或 require
的资源文件(resource file)所在的目录被认为是上下文目录(context directory)。在 import/require
中给定的相对路径,会添加此上下文路径(context path),以产生模块的绝对路径(absolute path)。
4 模块路径
import "module";
import "module/lib/file";
模块将会在resolve.modules中指定的全部目录内搜索,你能够替换初始模块路径,次替换路径经过使用resolve.alias配置一个别名。
一旦根据上述规则解析路径后,解析器将检查路径是否指向文件或目录。若是只想一个文件:
若是路径指向一个文件夹,则采起一下步骤找到具备正确扩展名的正确文件:
webpack根据构建目标为这些选项采用合理的默认配置。
5 解析loader 【Resolving Loaders】
Loader解析遵循与文件解析器指定的规则相同的规则。可是resolveLoader 配置选项能够用来为Loader提供独立解析规则。
6 缓存
每一个文件系统访问都被缓存,以便更快触发对同一文件的多个并行或串行请求。在观察模式下,只有修改过的文件会从缓存中摘出。若是关闭观察模式,在每次编译前清理缓存。
十 依赖图 【dependency graph】
任什么时候候,一个文件依赖于另外一个文件,webpack 就把此视为文件之间有依赖关系。这使得 webpack 能够接收非代码资源(non-code asset)(例如图像或 web 字体),而且能够把它们做为_依赖_提供给你的应用程序。
webpack 从命令行或配置文件中定义的一个模块列表开始,处理你的应用程序。 从这些入口起点开始,webpack 递归地构建一个依赖图,这个依赖图包含着应用程序所需的每一个模块,而后将全部这些模块打包为少许的 bundle- 一般只有一个 - 可由浏览器加载。
十一 构建目标
1 用法
在webpack配置中设置target的值
webpack.config.js
module.exports={ target:'node' }
在上面例子中,使用node webpack 会编译为用于[相似Node.js]环境(使用Node.js的require,而不是使用任意的内置模块(如 fs或path)来加载chunk)。
每一个target 都有各类部署/环境特定的附加项,以支持知足其需求。
2 多个target
webpack不支持向传入多个字符串,你能够经过打包两份分离配置来建立同构的库:
webpack.config.js
var path = require('path'); var serverConfig = { target: 'node', output:{ path:path.rsolve(_dirname,dist); fileName:'lib.nade.js' } …… }; var clientConfig = { target:'web', // 默认值是 ‘web’ ,可省略 output:{ path:path.resolve(_dirname,'dist'), filename:'lib.js' } …… }; module.exports=[serverConfig ,clientConfig ];
上面的例子将在你的 dist
文件夹下建立 lib.js
和 lib.node.js
文件。
十二 模块热替换
模块热替换功能会在应用程序过程当中替换,添加或删除模块,而无需从新加载整个页面。主要是经过如下几种方式,来显著加快开发速度。