Comment ai-je besoin ()/d'importer des modules depuis la console? Par exemple, disons que j'ai installé ImmutableJS npm, j'aimerais pouvoir utiliser les fonctions du module pendant que je travaille dans la console.
Voici une autre façon plus générique de le faire.
La version actuelle de WebPack expose webpackJsonp(...)
, qui peut être utilisée pour demander un module par ID:
function _requireById(id) {
return webpackJsonp([], null, [id]);
}
ou en TypeScript
window['_requireById'] =
(id: number): any => window['webpackJsonp'];([], null, [id]);
L'ID est visible en haut du module dans le fichier fourni ou dans le pied de page du fichier source d'origine servi via des cartes source.
Exiger un module par son nom est beaucoup plus délicat, car WebPack ne semble pas conserver de référence au chemin du module une fois toutes les sources traitées. Mais le code suivant semble faire l'affaire dans beaucoup de cas:
/**
* 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]
);
});
}
C'est un premier coup rapide, alors tout est à améliorer!
Inclure ceci dans un module permettra à require([modules], function)
d'être utilisé à partir d'un navigateur
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);
}
Exemple d'utilisation:
require(['jquery', 'immutable'], function($, immutable) {
// immutable and $ are defined here
});
Remarque: Chaque option d'instruction switch doit être soit quelque chose que ce module nécessite déjà, soit fournie par ProvidePlugin.
Basé sur cette réponse, qui peut être utilisée pour ajouter un dossier entier.
Méthode alternative de Documents Webpack - qui permet quelque chose comme require.yourModule.function()
Pouvoir utiliser les modules require
dans la console est pratique pour le débogage et l'analyse de code. La réponse de @ psimyn est très spécifique, vous ne pouvez donc pas conserver cette fonction avec tous les modules dont vous pourriez avoir besoin.
Lorsque j'ai besoin de l'un de mes propres modules à cette fin, je lui attribue une propriété de fenêtre pour pouvoir y accéder, par exemple window.mymodule = whatever_im_exporting;
. J'utilise le même truc pour exposer un module système si je veux jouer avec, par exemple:
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;
C'est toujours un peu pénible, mais en fouillant dans les bundles, je ne vois aucun moyen de mapper facilement les modules.
J'ai trouvé un moyen qui fonctionne, à la fois pour WebPack 1 et 2. (tant que la source n'est pas minifiée)
Repo: https://github.com/Venryx/webpack-runtime-require
npm install --save webpack-runtime-require
D'abord, exigez le module au moins une fois.
import "webpack-runtime-require";
Il ajoutera ensuite une fonction Require () à l'objet window, pour l'utiliser dans la console ou n'importe où dans votre code.
Ensuite, utilisez-le simplement, comme ceci:
let React = Require("react");
console.log("Retrieved React.Component: " + React.Component);
Ce n'est pas très joli (il utilise des expressions rationnelles pour rechercher les fonctions d'encapsulation du module) ou rapide (prend environ 50 ms le premier appel, et environ 0 ms après), mais ces deux choses sont parfaitement acceptables si elles ne servent qu'à tester la machine.
Ci-dessous une version recadrée de la source pour montrer comment cela fonctionne. (voir le repo pour le complet/dernier)
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;
}
Après avoir créé un module npm à cet effet (voir mon autre réponse ), j’ai fait une recherche sur npms.io et semble avoir trouvé un plugin webpack existant disponible à cet effet.
Repo: https://www.npmjs.com/package/webpack-expose-require-plugin
npm install --save webpack-expose-require-plugin
Ajoutez le plugin à votre configuration webpack, puis utilisez-le au moment de l'exécution de la manière suivante:
let MyComponent = require.main("./path/to/MyComponent");
console.log("Retrieved MyComponent: " + MyComponent);
Voir la page readme package/repo pour plus d'informations.
MODIFIER
J'ai essayé le plugin dans mon propre projet, mais je n'ai pas réussi à le faire fonctionner. J'ai gardé l'erreur: Cannot read property 'resource' of undefined
. Je vais le laisser ici au cas où cela fonctionnerait pour d'autres personnes, cependant. (J'utilise actuellement la solution mentionnée ci-dessus)
Après avoir créé mon propre paquet npm pour cela ( voir ici ), ainsi que trouver un fichier existant ( voir ici ), j’ai également trouvé un moyen de le faire en une ligne en utilisant seulement -dans les fonctions Webpack.
Il utilise les "contextes" WebPack: https://webpack.github.io/docs/context.html
Ajoutez simplement la ligne suivante à un fichier directement dans votre dossier "Source":
window.Require = require.context("./", true, /\.js$/);
Maintenant, vous pouvez l'utiliser (par exemple dans la console) comme ceci:
let MyComponent = Require("./Path/To/MyComponent");
console.log("Retrieved MyComponent: " + MyComponent);
Cependant, un inconvénient important de cette approche, par rapport aux deux solutions mentionnées ci-dessus, est qu’elle ne semble pas fonctionner pour les fichiers du dossier node_modules. Lorsque le chemin d'accès est réglé sur "../", Webpack ne parvient pas à se compiler - du moins dans mon projet. (peut-être parce que le dossier node_modules est tellement massif)
expose-loader est, à mon avis, une solution plus élégante:
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.
Ajouter le code ci-dessous à l'un de vos modules vous permettra de charger les modules par identifiant.
window.require = __webpack_require__;
Dans la console, utilisez les éléments suivants:
require(34)