我如何在控制台中使用require() / import导入模块?例如,假设我已经安装了ImmutableJS npm,我想在控制台中使用该模块的函数。
我如何在控制台中使用require() / import导入模块?例如,假设我已经安装了ImmutableJS npm,我想在控制台中使用该模块的函数。
这里有另一种更通用的方法。
WebPack 的当前版本暴露了 webpackJsonp(...)
,可用于按 ID 要求一个模块:
function _requireById(id) {
return webpackJsonp([], null, [id]);
}
或者使用TypeScript
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]
);
});
}
这只是快速尝试,所以所有内容都有待改进!
const id = 0;
。当我使用上面的代码(和其他一些字符串/数字)时,Promise从未解决。 - Venryxwindow.webpackJsonp 不是一个函数
:( 我需要引入什么吗? - SeptagramwebpackJsonp()
函数定义在哪里?它的参数是什么?在 webpack 的源代码中找不到。 - cprcrack在模块中包含此内容将允许从浏览器中使用 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
});
注意: 每个switch语句选项应该是这个模块已经要求的内容或由ProvidePlugin提供。
基于这个答案,可以用来添加整个文件夹。
另一种方法来自Webpack文档 - 允许像require.yourModule.function()
这样的操作。
require
到顶层上下文中? - amoenpm install --save webpack-runtime-require
首先,至少要引入一次该模块。
import "webpack-runtime-require";
接下来它会向window对象添加一个Require()函数,供控制台或代码中的任何位置使用。
然后只需像这样使用:
let React = Require("react");
console.log("Retrieved React.Component: " + React.Component);
这并不十分美观(它使用正则表达式来搜索模块包装函数),也不够快(第一次调用需要 ~50ms,之后为 ~0ms),但如果只是用于在控制台中进行hack测试,这两点都没问题。
以下是源代码的精简版本,以展示它的工作原理。 (有关完整/最新版本,请参见存储库)
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;
。如果我想要使用系统模块进行操作,我也会使用相同的技巧来公开它,例如:
myservice.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;
虽然有些麻烦,但是深入研究这些代码包,我发现没有方便的方法来映射模块。
// TODO: remove this
方面,因人而异。我更喜欢加载器而不是打包程序的原因之一是,您可以进行此类实验而无需更改代码,只需使用浏览器控制台即可。SystemJS.import('lodash').then(({default}) => window._ = default);
。我知道这个问题与Webpack有关,我只是在发牢骚,您必须承认这很不错。 - Aluan Haddaddefine
、require
/exports
)。 - Aluan Haddad@Rene Hamburger的答案很好,但不幸的是它已经不能用了(至少在我的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');
window.require = __webpack_require__;
require(34)
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.
在为此创建了一个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包(请看这里)以及找到一个现成的npm包(请看这里)之后,我还发现了一种只使用内置webpack函数就可以实现一行代码完成的方法。
它利用了Webpack的“上下文”功能:https://webpack.github.io/docs/context.html
只需要在你的“源”文件夹中的任意文件中添加以下代码即可:
window.Require = require.context("./", true, /\.js$/);
现在你可以像这样在控制台中使用它:
let MyComponent = Require("./Path/To/MyComponent");
console.log("Retrieved MyComponent: " + MyComponent);