webentwicklung-frage-antwort-db.com.de

Wie benötige ich () von der Konsole mit Webpack?

Wie benötige ich ()/importiere Module von der Konsole? Angenommen, ich habe die ImmutableJS npm installiert. Ich möchte die Funktionen des Moduls verwenden können, während ich in der Konsole arbeite.

38
Seth

Hier ist eine andere allgemeinere Methode, dies zu tun.

Anfordern eines Moduls nach ID

Die aktuelle Version von WebPack stellt webpackJsonp(...) bereit, mit der ein Modul nach ID angefordert werden kann:

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

oder in TypeScript

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

Die ID ist am oberen Rand des Moduls in der mitgelieferten Datei oder in der Fußzeile der ursprünglichen Quelldatei sichtbar, die über Quellkarten bereitgestellt wird.

Modul nach Namen anfordern

Das Anfordern eines Moduls anhand des Namens ist viel schwieriger, da WebPack scheinbar keinen Verweis auf den Modulpfad enthält, nachdem alle Quellen verarbeitet wurden. Der folgende Code scheint jedoch in vielen Fällen den Trick zu sein:

/**
 * 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]
    );
  });
}

Dies ist ein schneller erster Versuch, also ist alles zur Verbesserung bereit!

9
Rene Hamburger

Wenn Sie dies in ein Modul aufnehmen, kann require([modules], function) von einem Browser aus verwendet werden

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);
}

Verwendungsbeispiel:

require(['jquery', 'immutable'], function($, immutable) {
  // immutable and $ are defined here
});

Hinweis: Jede switch-statement-Option sollte entweder von diesem Modul bereits benötigt werden oder von ProvidePlugin bereitgestellt werden


Quellen:

Basierend auf dieser Antwort, die zum Hinzufügen eines gesamten Ordners verwendet werden kann.

Alternative Methode aus Webpack Docs - die etwas wie require.yourModule.function() erlaubt

9
psimyn

Die Verwendung von require-Modulen in der Konsole ist praktisch für das Debugging und die Code-Analyse. Die Antwort von @ psimyn ist sehr spezifisch, so dass Sie diese Funktion wahrscheinlich nicht mit allen Modulen aufrechterhalten, die Sie benötigen.

Wenn ich zu diesem Zweck eines meiner eigenen Module benötige, weise ich ihm eine Fenstereigenschaft zu, damit ich z. B. window.mymodule = whatever_im_exporting; darauf zugreifen kann. Ich benutze den gleichen Trick, um ein Systemmodul freizulegen, wenn ich damit spielen möchte, z.

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;

Es ist immer noch ein bisschen schmerzhaft, aber wenn ich mich in die Bündel stöbere, sehe ich keine Möglichkeit, die Module bequem zu kartieren.

2
Paul Whipp

Ich habe einen Weg gefunden, der sowohl für WebPack 1 als auch für 2 funktioniert. (Solange die Quelle nicht minimiert ist)

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

Installieren

npm install --save webpack-runtime-require

Verwendungszweck

Erstens, fordern Sie das Modul mindestens einmal an.

import "webpack-runtime-require";

Anschließend wird dem Fensterobjekt eine Require () - Funktion hinzugefügt, die in der Konsole oder an anderer Stelle in Ihrem Code verwendet werden kann.

Dann benutze es einfach so:

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

Es ist nicht sehr hübsch (es verwendet Regexes, um die Modul-Wrapper-Funktionen zu durchsuchen) oder schnell (dauert ~ 50ms beim ersten Aufruf und ~ 0ms danach), aber beide sind vollkommen in Ordnung, wenn es nur zum Testen von Hacks in der Konsole ist.

Technik

Im Folgenden finden Sie eine getrimmte Version der Quelle, um zu zeigen, wie sie funktioniert. (siehe Repo für die vollständige/letzte)

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

Nachdem ich hierfür ein npm-Modul erstellt hatte (siehe meine andere Antwort ), habe ich eine Suche auf npms.io durchgeführt und anscheinend ein vorhandenes Webpack-Plugin für diesen Zweck gefunden.

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

Installieren

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

Verwendungszweck

Fügen Sie das Plugin zu Ihrer Webpack-Konfiguration hinzu und verwenden Sie es zur Laufzeit wie folgt:

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

Weitere Informationen finden Sie auf der Readme-Seite zum Paket/Repo.

EDIT

Ich habe das Plugin in meinem eigenen Projekt ausprobiert, konnte es aber nicht zum Laufen bringen; Ich habe immer die Fehlermeldung erhalten: Cannot read property 'resource' of undefined. Ich lass es hier, falls es für andere Leute funktioniert. (Ich verwende stattdessen die oben erwähnte Lösung.)

0
Venryx

Nachdem beide ein eigenes npm-Paket dafür erstellt haben ( siehe hier ) und ein vorhandenes gefunden haben ( siehe hier ), habe ich auch einen Weg gefunden, dies in einer Zeile zu tun, nur mit dem eingebauten -in Webpack-Funktionen.

Es verwendet "Kontexte" von WebPack: https://webpack.github.io/docs/context.html

Fügen Sie einfach die folgende Zeile zu einer Datei direkt in Ihrem "Source" -Ordner hinzu:

window.Require = require.context("./", true, /\.js$/);

Jetzt können Sie es (z. B. in der Konsole) wie folgt verwenden:

let MyComponent = Require("./Path/To/MyComponent");
console.log("Retrieved MyComponent: " + MyComponent);

Ein wichtiger Nachteil dieses Ansatzes im Vergleich zu den beiden oben genannten Lösungen ist jedoch, dass er für Dateien im Ordner node_modules nicht zu funktionieren scheint. Wenn der Pfad auf "../" eingestellt ist, kann Webpack nicht kompiliert werden - zumindest in meinem Projekt. (Vielleicht weil der node_modules-Ordner einfach so massiv ist)

0
Venryx

Expose-Loader ist meiner Meinung nach eine elegantere Lösung: 

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.

Sie könnten etwas Ähnliches tun wie psimyn , das von .__ empfohlen wird, indem Sie einem Modul im Bundle folgenden Code hinzufügen:

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

Verwenden erfordern von der Konsole:

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

Mehr sehen

0
Milan Jaros

Wenn Sie den folgenden Code zu einem Ihrer Module hinzufügen, können Sie Module anhand der ID laden.

window.require = __webpack_require__;

Verwenden Sie in der Konsole Folgendes:

require(34)
0
lcharbon