我如何使用 webpack 从控制台要求()
How do I require() from the console using webpack?
如何要求((/从控制台导入模块?例如,假设我已经安装了不可变的 npm,我希望能够在控制台中工作时使用该模块中的函数。
这是另一种更通用的方法。
需要按 ID 显示模块
当前版本的 WebPack 公开了 webpackJsonp(...)
,可用于按 ID 要求模块:
function _requireById(id) {
return webpackJsonp([], null, [id]);
}
或在打字稿中
window['_requireById'] =
(id: number): any => window['webpackJsonp'];([], null, [id]);
该 ID 在捆绑文件中模块的顶部或通过源映射提供的原始源文件的页脚中可见。
按名称要求模块
按名称要求模块要棘手得多,因为 WebPack 在处理完所有源代码后似乎不会保留对模块路径的任何引用。但是以下代码似乎在很多情况下都可以解决问题:
/**
* Returns a promise that resolves to the result of a case-sensitive search
* for a module or one of its exports. `makeGlobal` can be set to true
* or to the name of the window property it should be saved as.
* Example usage:
* _requireByName('jQuery', '$');
* _requireByName('Observable', true)´;
*/
window['_requireByName'] =
(name: string, makeGlobal?: (string|boolean)): Promise<any> =>
getAllModules()
.then((modules) => {
let returnMember;
let module = _.find<any, any>(modules, (module) => {
if (_.isObject(module.exports) && name in module.exports) {
returnMember = true;
return true;
} else if (_.isFunction(module.exports) &&
module.exports.name === name) {
return true;
}
});
if (module) {
module = returnMember ? module.exports[name] : module.exports;
if (makeGlobal) {
const moduleName = makeGlobal === true ? name : makeGlobal as string;
window[moduleName] = module;
console.log(`Module or module export saved as 'window.${moduleName}':`,
module);
} else {
console.log(`Module or module export 'name' found:`, module);
}
return module;
}
console.warn(`Module or module export '${name}'' could not be found`);
return null;
});
// Returns promise that resolves to all installed modules
function getAllModules() {
return new Promise((resolve) => {
const id = _.uniqueId('fakeModule_');
window['webpackJsonp'](
[],
{[id]: function(module, exports, __webpack_require__) {
resolve(__webpack_require__.c);
}},
[id]
);
});
}
这是快速的第一枪,所以一切都有待改进!
将其包含在模块中将允许从浏览器使用require([modules], function)
window['require'] = function(modules, callback) {
var modulesToRequire = modules.forEach(function(module) {
switch(module) {
case 'immutable': return require('immutable');
case 'jquery': return require('jquery');
}
})
callback.apply(this, modulesToRequire);
}
示例用法:
require(['jquery', 'immutable'], function($, immutable) {
// immutable and $ are defined here
});
注意:每个开关语句选项都应该是这个模块已经需要的东西,或者由 ProvidePlugin 提供
<小时 />来源:
基于这个答案,可以用来添加整个文件夹。
来自 Webpack Docs 的替代方法 - 它允许类似 require.yourModule.function()
我找到了一种适用于 WebPack 1 和 2 的方法。(只要来源是非缩小的(
回购:https://github.com/Venryx/webpack-runtime-require
安装
npm install --save webpack-runtime-require
用法
首先,至少需要一次模块。
import "webpack-runtime-require";
然后,它会将 Require(( 函数添加到窗口对象,以便在控制台或代码中的任何位置使用。
然后使用它,如下所示:
let React = Require("react");
console.log("Retrieved React.Component: " + React.Component);
它不是很漂亮(它使用正则表达式来搜索模块包装器函数(或快速(第一次调用需要 ~50ms,之后需要 ~0ms(,但如果只是为了在控制台中进行黑客测试,这两个都很好。
技术
下面是源代码的修剪版本,以显示它是如何工作的。(有关完整/最新,请参阅存储库(
var WebpackData;
webpackJsonp([],
{123456: function(module, exports, __webpack_require__) {
WebpackData = __webpack_require__;
}},
[123456]
);
var allModulesText;
var moduleIDs = {};
function GetIDForModule(name) {
if (allModulesText == null) {
let moduleWrapperFuncs = Object.keys(WebpackData.m).map(moduleID=>WebpackData.m[moduleID]);
allModulesText = moduleWrapperFuncs.map(a=>a.toString()).join("'n'n'n");
// these are examples of before and after webpack's transformation: (which the regex below finds the var-name of)
// require("react-redux-firebase") => var _reactReduxFirebase = __webpack_require__(100);
// require("./Source/MyComponent") => var _MyComponent = __webpack_require__(200);
let regex = /var ([a-zA-Z_]+) = __webpack_require__'(([0-9]+)')/g;
let matches = [];
let match;
while (match = regex.exec(allModulesText))
matches.push(match);
for (let [_, varName, id] of matches) {
// these are examples of before and after the below regex's transformation:
// _reactReduxFirebase => react-redux-firebase
// _MyComponent => my-component
// _MyComponent_New => my-component-new
// _JSONHelper => json-helper
let moduleName = varName
.replace(/^_/g, "") // remove starting "_"
.replace(new RegExp( // convert chars where:
"([^_])" // is preceded by a non-underscore char
+ "[A-Z]" // is a capital-letter
+ "([^A-Z_])", // is followed by a non-capital-letter, non-underscore char
"g"),
str=>str[0] + "-" + str[1] + str[2] // to: "-" + char
)
.replace(/_/g, "-") // convert all "_" to "-"
.toLowerCase(); // convert all letters to lowercase
moduleIDs[moduleName] = parseInt(id);
}
}
return moduleIDs[name];
}
function Require(name) {
let id = GetIDForModule(name);
return WebpackData.c[id].exports;
}
能够在控制台中使用require
模块,便于调试和代码分析。 @psimyn的答案非常具体,因此您不太可能使用可能需要的所有模块来维护该功能。
当我为此目的需要自己的一个模块时,我会为它分配一个窗口属性,以便我可以使用它,例如window.mymodule = whatever_im_exporting;
。如果我想玩它,我会使用相同的技巧来公开系统模块,例如:
我的服务.js:
let $ = require('jquery');
let myService = {};
// local functions service props etc...
module.exports = myService;
// todo: remove these window prop assignments when done playing in console
window.$ = $;
window.myService = myService;
这仍然有点痛苦,但是深入研究捆绑包,我看不到任何可以方便地映射模块的方法。
@Rene汉堡包的答案很好,但不幸的是不再有效(至少在我的 webpack 版本中(。所以我更新了它:
function getWebpackInternals() {
return new Promise((resolve) => {
const id = 'fakeId' + Math.random();
window['webpackJsonp'].push(["web", {
[id]: function(module, __webpack_exports__, __webpack_require__) {
resolve([module, __webpack_exports__, __webpack_require__])
}
},[[id]]]);
});
}
function getModuleByExportName(moduleName) {
return getWebpackInternals().then(([_, __webpack_exports__, __webpack_require__]) => {
const modules = __webpack_require__.c;
const moduleFound = Object.values(modules).find(module => {
if (module && module.exports && module.exports[moduleName]) return true;
});
if (!moduleFound) {
console.log('couldnt find module ' + moduleName);
return;
}
return moduleFound.exports[moduleName];
})
}
getModuleByExportName('ExportedClassOfModule');
expose-loader是一个更优雅的解决方案:
require("expose-loader?libraryName!./file.js");
// Exposes the exports for file.js to the global context on property "libraryName".
// In web browsers, window.libraryName is then available.
将以下代码添加到其中一个模块将允许您按 id 加载模块。
window.require = __webpack_require__;
在控制台中,使用以下方法:
require(34)
你可以做一些类似于 psimyn 建议的事情将以下代码添加到捆绑包中的某个模块:
require.ensure([], function () {
window.require = function (module) {
return require(module);
};
});
使用控制台中的要求:
require("./app").doSomething();
查看更多
在为此制作了一个 npm 模块(请参阅我的另一个答案(之后,我在 npms.io 上进行了搜索,似乎已经找到了一个可用于此目的的现有 webpack 插件。
回购:https://www.npmjs.com/package/webpack-expose-require-plugin
安装
npm install --save webpack-expose-require-plugin
用法
将插件添加到您的 webpack 配置中,然后在运行时像这样使用:
let MyComponent = require.main("./path/to/MyComponent");
console.log("Retrieved MyComponent: " + MyComponent);
有关详细信息,请参阅包/存储库自述文件页。
编辑
我在自己的项目中尝试了该插件,但无法使其工作;我一直收到错误:Cannot read property 'resource' of undefined
。不过,我会把它留在这里,以防它适用于其他人。(我目前正在使用上面提到的解决方案(
制作了自己的 npm 包(见这里(以及找到一个现有的包(见这里(之后,我还找到了一种方法,只需使用内置的 webpack 函数就可以在一行中做到这一点。
它使用 WebPack "contexts": https://webpack.github.io/docs/context.html
只需将以下行直接添加到"源"文件夹中的文件中:
window.Require = require.context("./", true, /'.js$/);
现在您可以像这样使用它(例如在控制台中(:
let MyComponent = Require("./Path/To/MyComponent");
console.log("Retrieved MyComponent: " + MyComponent);
但是,与上述两种解决方案相比,此方法的一个重要缺点是它似乎不适用于node_modules文件夹中的文件。当路径调整为"../",webpack 无法编译——至少在我的项目中是这样。(也许是因为node_modules文件夹太大了(
- 如何使用Protractor从Chrome控制台获取所有日志
- 为什么控制台没有't使用输入的对象's的`toString`方法
- 我有可能防止黑客使用网络控制台用JavaScript重复调用upvote(AJAX)函数吗
- 执行JavaScript代码,使用selenium webdriver或WatiN从控制台获取日志
- 使用自定义选项从控制台运行JSlint
- 使用Dojo时需要控制台填充程序
- 如何使用注入Firefox控制台的js文本来更改网站的背景图像-示例提供
- 使用Javascript将图像属性输出到控制台
- 我如何使用 webpack 从控制台要求()
- 如何做if/else语句并使用控制台.log打印出来
- 使用 Websocket 的 Web 应用程序的虚拟控制台
- 如何使用 IE.au3 阅读 JavaScript 开发人员控制台
- 如何使用谷歌地理编码将地址转换为坐标后控制台日志数据
- 有没有一种方法可以在没有谷歌云控制台的情况下使用带有JavaScript的谷歌硬盘
- 有一种方法可以使jslint在使用控制台时显示警告或错误
- 使用奇怪的控制台日志结果向输入日期添加天数
- 使用javascript在HTML的输出窗口中打印控制台消息
- 为什么nodejs's require在此闭包中无法使用调试器控制台访问?可能的v8优化
- 为什么可以'我在亚马逊(控制台)中使用jQuery
- 是否可以使用 nw.js 构建控制台应用程序