webpack - Webpack'ing "sass" (dart-sass),使用需要动态、硬代码依赖到上下文?
问题描述
问题
“sass”包包含一个模块,sass.dart.js:https ://runpkg.com/?sass@1.21.0/sass.dart.js
除其他外,这包含require
(许多行已编辑)的动态用法:
var self = Object.create(global);
self.require = require;
//...
u($,"N0","Hq",function(){return self.require("readline")})
u($,"Mr","cN",function(){return self.require("fs")})
u($,"MN","Ho",function(){return self.require("chokidar")})
这种对 require 的使用会阻止 webpack 进行静态分析,从而导致输出中的错误(也在这个 gist 中)并在包中创建 webpackEmptyContext。这自然是行不通的:)
尝试过的选项
我看过ContextReplacementPlugin
,我认为这不适用于这里,因为用法不是直接的 require 调用。
我见过noParse
,但感觉就像核方法,我不知道潜在的负面影响可能是什么。
复制代码
同样在这个要点
index.js:
const sass = require("sass");
console.log(sass);
webpack.config.js:
module.exports = (env) => ({
entry: "./index.js",
mode: "development",
target: "node"
});
包.json:
{
"devDependencies": {
"webpack": "^4.34.0",
"webpack-cli": "^3.3.4"
},
"dependencies": {
"sass": "^1.21.0"
},
"scripts": {
"build": "webpack-cli"
}
}
目标
如何配置此特定模块的上下文以专门列出readline
//作为依赖项fs
,chokidar
可能会生成一些仅提供这些值的上下文?
我不介意解决方案是否有点脆弱并且需要固定 dart-sass 版本。
解决方案
我们已经找到了一个“解决方案”,它实现了一个自定义的、特定于 dart-sass 的加载器,以将代码添加到模块中以绕过静态分析。
sass-prepend-loader.js:
const SASS_PREPEND_CODE = `require = (function () {
var fs = require("fs");
var readline = require("readline");
return function (mod) {
switch (mod) {
case "fs": return fs;
case "readline": return readline;
default: throw new Error("Unexpected sass dependency");
}
};
})();`
module.exports = function(source) {
this.cacheable();
this.callback(null, `${SASS_PREPEND_CODE}\n${source}`);
};
webpack.config.js(摘录):
module: {
rules: [
{
resource: path.resolve(__dirname, "node_modules", "sass", "sass.dart.js"),
loader: path.resolve(__dirname, "sass-prepend-loader.js"),
}
],
},
这是专门为当前的“sass”版本 1.20.3 量身定制的,也可能是当前 webpack 中的行为。注意:我们没有通过“chokidar”依赖,我们的用例不需要它。
它通过分配require
只能提供“fs”和“readline”的版本来工作。Webpack 用调用替换了replace
被__webpack_require__
调用(满足静态分析的愿望)并允许require
(现在被隐藏)留下来。
从 dist/index.js 中提取:
/***/ (function(module, exports, __webpack_require__) {
(function(module, exports, __webpack_require__) {
eval("/* WEBPACK VAR INJECTION */(function(__filename) {var require;require = (function () {\n var fs = __webpack_require__(/*! fs */ \"fs\");\n var readline = __webpack_require__(/*! readline */ \"readline\");\n return function (mod) {\n switch (mod) {\n case \"fs\": return fs;\n case \"readline\": return readline;\n default: throw new Error(\"Unexpected sass dependency\");\n }\n };\n})();\n// make sure to keep this as 'var'\n// we don't want block scoping\nvar self = Object.create(global);\n\nself.scheduleImmediate = self.setImmediate\n ? function (cb) {\n global.setImmediate(cb);\n }\n : function(cb) {\n setTimeout(cb, 0);\n };\n\nself.require = require;
//...
self.require(\"fs\")
希望这是一个临时解决方案,我们可以通过以下途径之一找到更好的解决方案:
推荐阅读
- javascript - 鼠标事件的触发点击与切换
- codenameone - Android访问位置使登录屏幕放大效果
- c++ - 将 stl 字符串缩小到小于 15 个字符的容量
- php - 如何从原生 PHP 读取 Codeigniter 3 会话值?
- javascript - ShowText 中的文本着色以及调用变量?
- r - R中的多个列表JSON到数据框
- ios - SpriteKit iPhone/iPhoneX/iPad 尺寸问题
- junit - 问题 - JUNIT 验证信息添加到 Camel 路由标头
- php - 如何在 Wordpress 登录期间重定向用户?
- python - python 3.5 带括号和引号的语法错误