为什么 Webpack 不需要我们导入 'Loaders' 而 'Plugins' 呢?
Why Webpack doesn't need us to import 'Loaders' but 'Plugins' does?
我的问题是为什么在 Webpack 中导入 Loader 的行为方式与 Plugins 不同,以及为什么 Webpack 以不同的方式设计这两个导入。
const CssLoader = require('css-loader')
...
use:[new CssLoader()]
简而言之,加载器只是模块导出的函数,这些模块接收特定类型文件的源并将其 return 发送到下一个加载器或 Webpack 编译器。所有这些加载器函数都由 Webpack loader-runner 调用,因此 loader-runner 需要导出函数的路径。 ||大多数插件允许配置行为来初始化构造函数是最好的地方。无需新关键字即可添加插件
首先 Webpack 的加载器和插件是什么?
Webpack 只能理解 JavaScript 和 JSON 文件。可以使用加载器来处理文件以外的文件。由于 Webpack 将所有内容(JavaScript、图像、CSS、HTML...)视为一个模块,因此加载程序会转换模块。 babel-loader 将 ES6 转换为 browser-compatible JavaScript。还有其他装载机可以完成特定的工作。像 file-loader、URL-loader、CSS-loader、style-loader 等等。
您可以通过简单的步骤创建加载器
process-loader.js
module.exports = function dummyLoader(source) {
console.log(source);
return source;
}
并添加 modules.rule
以处理特定文件。
module: {
rules: [
{
test: /\.js$/,
use: ['babel-loader', path.resolve(__dirname, './process-loader')]
}
]
}
这里每个 .js
文件都必须经过加载程序。首先,它将通过 babel-loader。 babel-loader 将转换输入源和 return 已处理代码。处理后的代码将传递给 process-loader(导出的模块)。它可以处理源和 return 或 return 作为它。
Loader is nothing but a function exported by JavaScript Module. And this function is called by Webpack loader-runner. Webpack loader-runner knows how to find loader from path, either it will look into node modules or other local file path. It receives source code as a parameter and returned it to the Webpack loader-runner. That returned code is passed down to the next loader. If you remove return source
from process-loader.js
you will end up with a white screen as the source is not returned and null passed to the next loader. The source from the last loader in the chain is passed down to the Webpack compiler for bundling. And due to this sequence of the loader is also essential.
在链式加载器中,Webpack 以相反的顺序调用加载器,即从右到左。
对于下面的链式装载机
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: ["style-loader", "css-loader", "sass-loader",],
}
]
}
可以像这样形象化,
为什么以及如何反转,查看 Webpack Pitching Loaders
您可以找到更多关于装载机的有趣内容 here
插件只不过是 Javascript 暴露 apply 方法的对象。插件有助于编译器和编译。插件可以挂接到 Webpack 的各个生命周期阶段。该插件可以使用 compiler hooks like beforeRun, run, watchRun, compile and many more or compilation hooks 管理输出,例如 optimizeAssets、processAssets。
创建插件的标准方式
const PLUGIN_NAME = 'DemoPlugin';
class DemoPlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
}
}
module.exports = DemoPlugin;
并添加到 webpack. plugins
const DemoPlugin = require('./DemoPlugin');
...
plugins:[
new DemoPlugin({/*some config*/})
]
如果你想避免新的关键字,你可以简单地用apply方法导出对象
module.exports = {
apply(compiler) {
compiler.hooks.watchRun.tap('WatchRun', (comp) => {
console.log(' just watching')
});
}
}
并传递给 webpack.plugins
plugins: [
require('./DummyPlugin')
]
或
const DummyPlugin = require('./DummyPlugin');
...
plugins: [
DummyPlugin
]
使用 new 关键字,您只是避免使用构造函数初始化模块并传递配置
您甚至可以使用 apply 方法将对象直接添加到插件数组中。
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, './public/index.html')
}),
{
apply(compiler) {
compiler.hooks.watchRun.tap('WatchRun', (comp) => {
console.log(' just watching')
});
}
}
]
效果一样。这是为了方便,而不是强制。
我的问题是为什么在 Webpack 中导入 Loader 的行为方式与 Plugins 不同,以及为什么 Webpack 以不同的方式设计这两个导入。
const CssLoader = require('css-loader')
...
use:[new CssLoader()]
简而言之,加载器只是模块导出的函数,这些模块接收特定类型文件的源并将其 return 发送到下一个加载器或 Webpack 编译器。所有这些加载器函数都由 Webpack loader-runner 调用,因此 loader-runner 需要导出函数的路径。 ||大多数插件允许配置行为来初始化构造函数是最好的地方。无需新关键字即可添加插件
首先 Webpack 的加载器和插件是什么?
Webpack 只能理解 JavaScript 和 JSON 文件。可以使用加载器来处理文件以外的文件。由于 Webpack 将所有内容(JavaScript、图像、CSS、HTML...)视为一个模块,因此加载程序会转换模块。 babel-loader 将 ES6 转换为 browser-compatible JavaScript。还有其他装载机可以完成特定的工作。像 file-loader、URL-loader、CSS-loader、style-loader 等等。
您可以通过简单的步骤创建加载器
process-loader.js
module.exports = function dummyLoader(source) {
console.log(source);
return source;
}
并添加 modules.rule
以处理特定文件。
module: {
rules: [
{
test: /\.js$/,
use: ['babel-loader', path.resolve(__dirname, './process-loader')]
}
]
}
这里每个 .js
文件都必须经过加载程序。首先,它将通过 babel-loader。 babel-loader 将转换输入源和 return 已处理代码。处理后的代码将传递给 process-loader(导出的模块)。它可以处理源和 return 或 return 作为它。
Loader is nothing but a function exported by JavaScript Module. And this function is called by Webpack loader-runner. Webpack loader-runner knows how to find loader from path, either it will look into node modules or other local file path. It receives source code as a parameter and returned it to the Webpack loader-runner. That returned code is passed down to the next loader. If you remove
return source
fromprocess-loader.js
you will end up with a white screen as the source is not returned and null passed to the next loader. The source from the last loader in the chain is passed down to the Webpack compiler for bundling. And due to this sequence of the loader is also essential.
在链式加载器中,Webpack 以相反的顺序调用加载器,即从右到左。
对于下面的链式装载机
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: ["style-loader", "css-loader", "sass-loader",],
}
]
}
可以像这样形象化,
为什么以及如何反转,查看 Webpack Pitching Loaders
您可以找到更多关于装载机的有趣内容 here
插件只不过是 Javascript 暴露 apply 方法的对象。插件有助于编译器和编译。插件可以挂接到 Webpack 的各个生命周期阶段。该插件可以使用 compiler hooks like beforeRun, run, watchRun, compile and many more or compilation hooks 管理输出,例如 optimizeAssets、processAssets。
创建插件的标准方式
const PLUGIN_NAME = 'DemoPlugin';
class DemoPlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
}
}
module.exports = DemoPlugin;
并添加到 webpack. plugins
const DemoPlugin = require('./DemoPlugin');
...
plugins:[
new DemoPlugin({/*some config*/})
]
如果你想避免新的关键字,你可以简单地用apply方法导出对象
module.exports = {
apply(compiler) {
compiler.hooks.watchRun.tap('WatchRun', (comp) => {
console.log(' just watching')
});
}
}
并传递给 webpack.plugins
plugins: [
require('./DummyPlugin')
]
或
const DummyPlugin = require('./DummyPlugin');
...
plugins: [
DummyPlugin
]
使用 new 关键字,您只是避免使用构造函数初始化模块并传递配置 您甚至可以使用 apply 方法将对象直接添加到插件数组中。
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, './public/index.html')
}),
{
apply(compiler) {
compiler.hooks.watchRun.tap('WatchRun', (comp) => {
console.log(' just watching')
});
}
}
]
效果一样。这是为了方便,而不是强制。