2014-10-28 16 views
16

Ziehen Sie meine Haare hier auf der Suche nach einer einfachen Lösung zum Teilen von Code, benötigt über NPM, über mehrere Browserify oder Webpack Bundles. Denken, gibt es so etwas wie eine Datei "Brücke"?Einfache Lösung zum Teilen von Modulen, die über NPM über mehrere Browserify- oder Webpack-Bundles verteilt sind

Dies ist nicht rechtzeitig zu kompilieren (ich bin mir dessen bewusst watchify), sondern der Wunsch, alle meine herstellerspezifischen Libs in vendor.js zu extrahieren so über meine app.js Dateigröße zu halten und nicht den Browser zum Absturz zu bringen mit massiven Quellkarten. Außerdem finde ich es sauberer, wenn die Notwendigkeit besteht, die kompilierten js zu sehen. Und so:

// vendor.js 

require('react'); 
require('lodash'); 
require('other-npm-module'); 
require('another-npm-module'); 

Es ist sehr wichtig, dass der Code von NPM geladen werden, da zu Bower im Gegensatz oder in einem gewissen ‚Anbieter‘ Verzeichnis gespeichert, um über einen relativen Pfad importiert zu werden und über eine Shim identifiziert. Ich möchte, dass jede Bibliotheksreferenz über NPM abgerufen wird, mit Ausnahme meiner eigentlichen Anwendungsquelle.

In app.js halte ich alle meine Sourcecode und über die externals Array ausschließen Anbieter Bibliotheken oben aus der Kompilierung aufgeführt:

// app.js 

var React = require('react'); 
var _  = require('lodash'); 

var Component = React.createClass() 

// ... 

Und dann in index.html, benötige ich beide Dateien

// index.html 
<script src='vendor.js'></script> 
<script src='app.js'></script> 

Wie kann ich mit Browserify oder Webpack so arbeiten, dass app.js in das über npm geladene Modul "hineinsehen" kann? Ich bin mir bewusst, ein Bündel mit externen Elementen zu erstellen und dann auf die direkte Datei (in, sagen wir node_modules) über einen Alias ​​zu verweisen, aber ich hoffe, eine Lösung zu finden, die mehr automatisch ist und weniger "Require.js".

Grundsätzlich frage ich mich, ob es möglich ist, die beiden zu überbrücken, so dass app.jsvendor.js nach innen schauen können, um Abhängigkeiten aufzulösen. Dies scheint eine einfache, unkomplizierte Operation zu sein, aber ich kann nirgendwo auf diesem weiten, weiten Netz eine Antwort finden.

Danke!

Antwort

11

Mit Webpack verwenden Sie mehrere Einstiegspunkte und die CommonChunkPlugin.

vom webpack docs Genommen:


Ihre App in zwei Dateien aufgeteilt, sagen app.js und vendor.js Sie die Herstellerdateien in vendor.js erfordern kann. Übergeben Sie diesen Namen dann an das CommonChunkPlugin wie unten gezeigt.

module.exports = { 
    entry: { 
    app: "./app.js", 
    vendor: ["jquery", "underscore", ...], 
    }, 
    output: { 
    filename: "bundle.js" 
    }, 
    plugins: [ 
    new webpack.optimize.CommonsChunkPlugin(
     /* chunkName= */"vendor", 
     /* filename= */"vendor.bundle.js" 
    ) 
    ] 
}; 

Dadurch werden alle Module im Lieferanten-Chunk aus dem App-Chunk entfernt. Die bundle.js enthält jetzt nur Ihren App-Code ohne Abhängigkeiten. Diese sind in vendor.bundle.js.

Laden Sie in Ihrer HTML-Seite vendor.bundle.js vor bundle.js.

<script src="vendor.bundle.js"></script> 
<script src="bundle.js"></script> 

+0

Ich gehe davon reagieren geht im Kreditoren Array auch? – Leahcim

+0

enthalten Sie nur den Namen der Herstellerdatei in diesem Array oder sollte es ein Pfad zu diesem sein? – Leahcim

+0

Ich möchte kein separates Paket oder Chunk für meine separate Bibliothek von Komponenten erstellen, die ich zwischen Projekten teile. Ich möchte nur die Quelldateien direkt benötigen. Kennst du einen Weg, dies zu tun? (vollständige Frage: http://stackoverflow.com/questions/31820641/how-to-set-up-a-private-shared-library-of-react-components-with-webpack) – Andy

26

Auflisten der alle Herstellerdateien/Module und mit CommonChunkPlugin tatsächlich Weise die empfohlene ist. Dies wird jedoch ziemlich mühsam und fehleranfällig.

Betrachten Sie diese NPM-Module: fastclick und mprogress. Da sie die CommonJS Modulformat nicht angenommen haben, müssen Sie webpack eine Hand, wie diese geben:

require('imports?define=>false!fastclick')(document.body); 
require('mprogress/mprogress.min.css'); 
var Mprogress = require('mprogress/mprogress.min.js'), 

Jetzt vorausgesetzt, Sie in Ihrem Anbieter chunk sowohl fastclick und mprogress wollen würde, würden Sie wahrscheinlich versuchen, diese:

module.exports = { 
    entry: { 
    app: "./app.js", 
    vendor: ["fastclick", "mprogress", ...] 

Leider funktioniert es nicht. Sie müssen die Anrufe require() zum Spiel:

module.exports = { 
    entry: { 
    app: "./app.js", 
    vendor: [ 
     "imports?define=>false!fastclick", 
     "mprogress/mprogress.min.css", 
     "mprogress/mprogress.min.js", 
     ...] 

Es alt wird, sogar mit einigen resolve.alias Tricks. Hier ist meine Problemumgehung. Mit CommonChunkPlugin können Sie einen Rückruf angeben, der zurückgibt, ob ein Modul in den Lieferantenabschnitt aufgenommen werden soll oder nicht. Wenn Sie Ihre eigene Code Quelle in einem bestimmten src Verzeichnis ist, und der Rest ist im node_modules Verzeichnis, lehnt nur die Module auf ihrem Weg basieren:

var node_modules_dir = path.join(__dirname, 'node_modules'), 
    app_dir   = path.join(__dirname, 'src'); 

module.exports = { 
    entry: { 
    app: "./app.js", 
    }, 
    output: { 
    filename: "bundle.js" 
    }, 
    plugins: [ 
    new webpack.optimize.CommonsChunkPlugin(
     /* chunkName= */"vendor", 
     /* filename= */"vendor.bundle.js" 
     function (module, count) { 
     return module.resource && module.resource.indexOf(app_dir) === -1; 
     } 
    ) 
    ] 
}; 

Wo module.resource den Pfad zum Modul berücksichtigt werden. Man könnte auch das Gegenteil tun und umfasst nur das Modul, wenn es innerhalb node_modules_dir ist, das heißt:

 return module.resource && module.resource.indexOf(node_modules_dir) === 0; 

aber in meiner Situation, würde ich eher sagen: "alles setzen, die nicht in meinem Source-Source-Tree ist in einem Lieferantenbrocken ".

Hoffe, dass hilft.

+0

ist die Datei './App.js' im Verzeichnis 'src'? – Leahcim

+0

auch, wie funktioniert das, wo Sie npm-Module haben, die Sie für die Entwicklung verwenden, aber nicht in einer Produktionsherstellerdatei möchten? sagen wir zum Beispiel, dass Sie "Backbone.js" und "underscore.js" als 'node_module' haben, die Sie in der Vendor-Datei benötigen, aber auch andere' node_modules' haben, die nur für Dev-Zwecke enthalten sind und Sie nicht wollen gebündelt in einem 'vendor.bundle.js' – Leahcim

+0

@Leahcim sieht es aus wie eine Entscheidung, die Sie machen müssen, wenn Sie die" dev only "Module laden, nicht in der Datei webpack.config. Sie könnten etwas wie das 'DefinePlugin' verwenden, um ein' IS_DEV' zu definieren und bedingt Ihre dev node_module. Wenn Sie dann kompilieren, wenn 'IS_DEV' false ist, wird es nicht geladen –