Comment puis-je exiger () de la console à l'aide d'un webpack?

Comment puis-je () / importer des modules de 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.

En incluant ceci dans un module, il faudra require([modules], function) à 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 de déclaration de commutation devrait être soit ce module déjà requis, soit fourni par ProvidePlugin


Sources:

Basé sur cette réponse , qui peut être utilisé pour ajouter un dossier entier.

Méthode alternative de Webpack Docs – qui permet à quelque chose comme require.yourModule.function()

Voici une autre façon plus générique de faire cela.

Exiger un module par ID

La version actuelle de WebPack expose webpackJsonp(...) , qui peut être utilisé pour exiger un module par ID:

 function _requireById(id) { return webpackJsonp([], null, [id]); } 

Ou dans TypeScript

 window['_requireById'] = (id: number): any => window['webpackJsonp'];([], null, [id]); 

L'ID est visible en haut du module dans le fichier groupé ou dans le pied de page du fichier source d'origine fourni via les cartes source.

Exiger un module par nom

L'exigence d'un module par nom est beaucoup plus délicate, car WebPack ne semble pas conserver de référence au chemin du module une fois qu'il a traité toutes les sources. Mais le code suivant semble faire l'énigme 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 de feu rapide, donc tout va bien pour l'amélioration!

Après avoir fait mon propre paquet npm pour cela ( voir ici ), ainsi que pour en trouver un existant ( voir ici ), j'ai également trouvé un moyen de le faire en une seule ligne en utilisant simplement les fonctions de stockage Web intégrées.

Il utilise WebPack "contextes": 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 (p. Ex. Dans la console) de la manière suivante:

 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'il ne semble pas fonctionner pour les fichiers dans le dossier node_modules. Lorsque le chemin d'accès est ajusté à "../", le logiciel ne parvient pas à compiler – au moins dans mon projet. (Peut-être parce que le dossier node_modules est tellement important)

Être capable d'utiliser require 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, donc vous ne risquez pas de maintenir cette fonction avec tous les modules dont vous pourriez avoir besoin.

Lorsque j'ai besoin d'un de mes propres modules à cet effet, je lui attribue une propriété de fenêtre afin que je puisse y accéder, par exemple window.mymodule = whatever_im_exporting; . J'utilise la même astuce pour exposer un module système si je veux jouer avec ça, 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 encore une douleur, mais en train de creuser dans les paquets, je ne vois aucun moyen de localiser de manière appropriée les modules.

Vous pouvez faire quelque chose de similaire à celui de psimyn conseillé en ajoutant le code suivant à un module en bundle:

 require.ensure([], function () { window.require = function (module) { return require(module); }; }); 

Utilisation de la console:

 require("./app").doSomething(); 

Voir plus

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. 

Après avoir fait un module npm pour cela (voir mon autre réponse ), j'ai effectué une recherche sur npms.io et semblent avoir trouvé un plug-in Web existant disponible à cette fin.

Repo: https://www.npmjs.com/package/webpack-expose-require-plugin

Installer

 npm install --save webpack-expose-require-plugin 

Usage

Ajoutez le plugin à votre configuration de serveur Web, puis utilisez-le au moment de l'exécution comme suit:

 let MyComponent = require.main("./path/to/MyComponent"); console.log("Retrieved MyComponent: " + MyComponent); 

Voir la page readme / repo readme pour plus d'informations.

MODIFIER

J'ai essayé le plugin dans mon propre projet, mais je n'ai pas pu le faire fonctionner; J'ai continué à obtenir l'erreur: Cannot read property 'resource' of undefined . Je vais le laisser ici si cela fonctionne pour d'autres personnes, cependant. (J'utilise actuellement la solution mentionnée ci-dessus)

J'ai trouvé un moyen qui fonctionne, tant pour les WebPack 1 et 2. (tant que la source n'est pas minifiée)

Repo: https://github.com/Venryx/webpack-runtime-require

Installer

 npm install --save webpack-runtime-require 

Usage

Tout d'abord, requiert le module au moins une fois.

 import "webpack-runtime-require"; 

Il ajoutera ensuite une fonction Require () à l'objet fenêtre, à utiliser dans la console ou n'importe où dans votre code.

Ensuite, utilisez-le, ainsi:

 let React = Require("react"); console.log("Retrieved React.Component: " + React.Component); 

Ce n'est pas très joli (il utilise des regexes pour rechercher les fonctions de l'enveloppe du module) ou rapide (prend environ 50 ms le premier appel et ~ 0 ms après), mais tous deux sont parfaitement bien si c'est juste pour les tests de piratage dans la console.

Technique

Voici une version découpée de la source pour montrer comment cela fonctionne. (Voir le remboursement 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 + "[AZ]" // 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; } 

L'ajout du code ci-dessous à l'un de vos modules vous permettra de charger des modules par identifiant.

 window.require = __webpack_require__; 

Dans la console, utilisez les éléments suivants:

 require(34)