(我正在使用Webpack 3.8.1)
我有一个包含此问题所示代码的回购:
https://github.com/leoasis/webpack-loader-issue
我正在尝试编写一个webpack加载器来处理源代码的内容并生成一些值。如果源依赖于其他资源,我需要在加载器中加载它们来计算该值,因为它取决于依赖项的值。为此,我使用this.loadModule
并在加载模块后立即访问该值。
然而,当我有依赖关系的依赖时,这似乎失败了,因为它们似乎没有包含在最终的包中,导致错误。
以下是重现案例的缩小示例:
// webpack.config.js
const path = require('path');
module.exports = {
entry: './a.js',
output: {
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
use: './foo-loader'
}
]
}
};
// a.js
import './b';
console.log('Hello from a');
// b.js
import './c';
console.log('Hello from b');
// c.js
console.log('Hello from c');
最后,加载器:
// foo-loader.js
module.exports = function (content) {
this.async();
const dep = content.split('\n')[0].split('\'')[1];
this._module.someValue = dep.charCodeAt(2); // gets the 'a' from './a'
if (dep[0] !== '.') {
this.callback(null, content + 'console.log("the value is", ' + this._module.someValue + ')');
return;
}
this.loadModule(dep, (err, source, sourceMap, module) => {
if (err) {
this.callback(err);
return;
}
this._module.someValue += module.someValue;
console.log(this.resourcePath, this._module.someValue);
this.callback(null, content + 'console.log("the value is", ' + this._module.someValue + ')');
});
}
这是结果包:
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 1);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
throw new Error("Cannot find module \"./c\"");
console.log('Hello from b');
console.log("the value is", 207)
/***/ }),
/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__b__ = __webpack_require__(0);
console.log('Hello from a');
console.log("the value is", 305)
/***/ })
/******/ ]);
请注意,如果找不到模块./c
,会出现错误如果我将加载程序更改为标识符,则此工作完全正常:
module.exports = function (content) {
return content;
}
它甚至失败了,只需调用this.loadModule
并且对响应没有任何作用的普通装载程序。
module.exports = function (content) {
const dep = content.split('\n')[0].split('\'')[1];
if (dep[0] !== '.') {
return content;
}
this.loadModule(dep, () => { console.log('loading', dep); });
return content;
}
有人知道会发生什么吗?这是this.loadModule
的预期行为吗?这是一个错误吗?如果它不是一个错误,我怎么能加载一个模块但仍然使它成为一部分?
答案 0 :(得分:0)
好的经过一些研究后我在Webpack回购中发现了这个问题https://github.com/webpack/webpack/issues/4959,它讨论了同样的事情。问题是loadModule
不加载模块'依赖性递归。理想情况下,这应该在webpack中的loadModule函数中得到支持,可能在loadModule
中有一个选项,但是现在解决方法是从Webpack复制定义loadModule
方法的代码({{3并且更改标志以递归加载模块为true,如https://github.com/webpack/webpack/blob/master/lib/dependencies/LoaderPlugin.js。
基本上,改变这个:
compilation.addModuleDependencies(module, [
[dep]
], true, "lm", false, (err) => {
对此:
compilation.addModuleDependencies(module, [
[dep]
], true, "lm", true, (err) => {
我仍然不太相信这个解决方案是正确的,特别是因为我对Webpack的代码库不太熟悉,但它适用于我的用例,所以我'将其标记为已接受的答案,直到出现更好的解决方案。