【自用】
Webpack提供了node.js API,可以在Node.js运行时下直接使用。
Webpack仅仅负责编译,其他报告,错误处理都需要自行实现,stats配置选项不会在webpack()调用中生效。
安装
开始使用Node.js API之前需要安装webpack和引入。
npm install --save-dev webpack
const webpack = require('webpack');
复制代码
或者使用ES2015。
import webpack from 'webpack';
复制代码
webpack()
导入的webpack函数会将配置对象传给webpack,如果同时传入回调函数,会在webpack compiler
运行时被执行。
const webpack = require('webpack');
webpack({
// [配置对象](/configuration/)
}, (err, stats) => { // [Stats Object](#stats-object)
if (err || stats.hasErrors()) {
// [在这里处理错误](#error-handling)
}
// 处理完成
});
复制代码
err
对象不包含编译错误,需要使用stats.hasErrors()
单独处理。err
对象只包含webpack相关的问题,例如配置错误等。
也可以为webpack函数提供一个配置数组,后续详解。
Compiler实例
如果不向webpack传入可执行的回调函数,它会返回一个webpack compiler实例。
可以通过手动执行它或者为它的构建时添加一个监听器。
Compiler实例提供了以下方法。
.run(callback)
.watch(watchOptions, handler)
通常仅会创建一个主要Compiler实例。Compiler基本上只是执行最低限度的功能,维持生命周期运行。其他加载、打包、写入工作都委托到注册的插件上。
Compiler实例上的hooks属性用于将插件注册到Compiler的生命周期中的钩子事件上。
webpack使用WebpackOptionsDefaulter
和WebpackOptionsApply
来配置Compiler实例和内置插件。
使用run方法启动所有编译工作。完成之后执行传入的callback函数。最终记录下来的stats和errors都在这个callback中获取。
这个API一次仅支持一次编译。不能并发编译。一次run或者watch,需要调用close等待其完成后才能再次执行run和watch。
执行(Run)
const webpack = require('webpack');
const compiler = webpack({
// [配置对象](/configuration/)
});
compiler.run((err, stats) => { // [Stats Object](#stats-object)
// ...
compiler.close((closeErr) => {
// ...
});
});
复制代码
监听(Watching)
调用watch方法会出发webpack执行,一旦webpack检测到文件变更,就会重新执行编译。
该方法会返回一个Watching实例。
watch(watchOptions, callback);
复制代码
const webpack = require('webpack');
const compiler = webpack({
// [配置对象](/configuration/)
});
const watching = compiler.watch({
// [watchOptions](/configuration/watch/#watchoptions) 示例
aggregateTimeout: 300,
poll: undefined
}, (err, stats) => { // [Stats Object](#stats-object)
// 这里打印 watch/build 结果...
console.log(stats);
});
复制代码
关闭Watching(Close Watching)
watch方法返回一个Watching实例,该实例暴露一个.close(callback)方法,调用其方法会结束监听。
watching.close((closeErr) => {
console.log('Watching Ended.');
});
复制代码
不能在监听器关闭或者失效之前再次watch或run。
Invalidate Watching
使用watching.invalidate
可以手动使当前编译循环无效,但不会停止监听进程。
Stats对象
stats对象会被作为webpack()回调函数的第二个参数,可以通过它获取代码编译过程中的有用信息,比如:
- 错误和警告
- 计时信息
- module和chunk信息
webpack CLI正是基于这些信息在控制台展示输出。
stats对象暴露了以下方法。
stats.hasErrors()
用来检查编译期是否有错,返回值为boolean。
stats.hasWarnings()
同上。
stats.toJson(options)
以JSON对象形式返回编译信息。options可以是字符串或者对象。
stats.toJson('minimal'); // [更多选项如: 'verbose' 等](/configuration/stats).
复制代码
stats.toJson({
assets: false,
hash: true,
});
复制代码
stats.toString(options)
以格式化的字符串形式返回编译信息。
配置对象与toJson一致,额外增加一个
stats.toString({
// 增加控制台颜色开关
colors: true,
});
复制代码
用法示例。
const webpack = require('webpack');
webpack({
// [配置对象](/configuration/)
}, (err, stats) => {
if (err) {
console.error(err);
return;
}
console.log(stats.toString({
chunks: false, // 使构建过程更静默无输出
colors: true // 在控制台展示颜色
}));
});
复制代码
MultiCompiler
可以让webpack同时执行多个配置。传给webpack 的options参数是由多个配置对象构成的数组,webpack会相应地创建多个Compiler示例,并且在所有compiler执行完毕后,调用callback方法。
var webpack = require('webpack');
webpack([
{ entry: './index1.js', output: { filename: 'bundle1.js' } },
{ entry: './index2.js', output: { filename: 'bundle2.js' } }
], (err, stats) => { // [Stats Object](#stats-object)
process.stdout.write(stats.toString() + '\n');
})
复制代码
多个配置对象在具体执行时不会并行执行。
错误处理(Error Handling)
完备的错误处理需要考虑以下三种类型的错误:
- 致命的webpack错误(配置出错)
- 编译错误
- 编译警告
覆盖这些场景的示例。
const webpack = require('webpack');
webpack({
// [配置对象](/configuration/)
}, (err, stats) => {
if (err) {
console.error(err.stack || err);
if (err.details) {
console.error(err.details);
}
return;
}
const info = stats.toJson();
if (stats.hasErrors()) {
console.error(info.errors);
}
if (stats.hasWarnings()) {
console.warn(info.warnings);
}
// Log result...
});
复制代码
自定义文件系统(Custom File Systems)
默认情况下webpack使用普通文件系统来读取文件并写入。但是还可以使用不同类型的文件系统来更改。
改变inputFileSystem
或outputFileSystem
来实现。
例如,可以使用memfs
替换默认的outputFileSystem
,将文件写入到内存中。
const { createFsFromVolume, Volume } = require('memfs');
const webpack = require('webpack');
const fs = createFsFromVolume(new Volume());
const compiler = webpack({
/* options */
});
compiler.outputFileSystem = fs;
compiler.run((err, stats) => {
// 之后读取输出:
const content = fs.readFileSync('...');
compiler.close((closeErr) => {
// ...
});
});
复制代码
webpack-dev-server
及众多包依赖的webpack-dev-middleware
就是通过这种方式将文件放入内存中而不是磁盘中。
指定的输出文件系统需要兼容Node自身的fs模块接口。