web-dev-qa-db-fra.com

Comment ai-je besoin () de la console à l'aide de Webpack?

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.

38
Seth

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

Requérant un module par ID

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.

Requérant un module par nom

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!

9
Rene Hamburger

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.


Sources:

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()

9
psimyn

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.

2
Paul Whipp

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

Installer

npm install --save webpack-runtime-require

Usage

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.

Technique

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;
}
1
Venryx

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

Installer

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

Usage

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)

0
Venryx

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)

0
Venryx

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.
0
Ovidiu S.

Vous pouvez faire quelque chose de similaire à psimyn conseillé par En ajoutant le code suivant à un module de l’ensemble:

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

Utilisez require de la console:

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

Voir plus

0
Milan Jaros

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)
0
lcharbon