2017-09-26 3 views
0

Ich migriere von einem RequireJS-Projekt zu Webpack. Letzteres ist neu für mich, ich benutze dies als eine Lernübung. In RequireJS konnte ich Sachen wie diese registrieren:Webpack 2: Shimming wie RequireJS für jQWidgets?

shim: { 
    'jqxcore': { 
     exports: "$", 
     deps: ["jquery"] 
    }, 
    'jqxtree': { 
     exports: "$", 
     deps: ["jquery", "jqxcore"] 
    }, 
    'jqxbutton': { 
     exports: "$", 
     deps: ["jquery", "jqxcore"] 
    }, 
    'jqxsplitter': { 
     exports: "$", 
     deps: ["jquery", "jqxcore"] 
    }, 
    'jqxmenu': { 
     exports: "$", 
     deps: ["jquery", "jqxcore"] 
    } 
} 

und dann benötigen nur „jqxsplitter“ zum Beispiel wie folgt:

import "jqxsplitter" 

und Sachen richtig registriert werden würde und geladen. Jetzt habe ich ein paar Guides/Tutorials/Takes gesehen, die ich bei der Migration von RequireJS zu Webpack gefunden habe, wie this eins und this eins. So folgt diese Einsichten Ich versuche, so etwas wie dies in meinem webpack.config.js:

"use strict"; 

// Required to form a complete output path 
const path = require("path"); 

// Plagin for cleaning up the output folder (bundle) before creating a new one 
const CleanWebpackPlugin = require("clean-webpack-plugin"); 

const HtmlWebpackPlugin = require("html-webpack-plugin"); 
const webpack = require("webpack"); 

// Path to the output folder 
const bundleFolder = "./wwwroot/"; 

// Path to the app source code 
const appFolder = "./app/"; 

module.exports = { 
    // Application entry point 
    entry: { 
     main: appFolder + "index.ts", 
     vendor: [ 
      "knockout", 
      "jquery", 
      "jqxcore" 
     ], 
     jqxsplitter: "jqxsplitter" 
    }, 

    // Output file 
    output: { 
     filename: "[name].js", 
     chunkFilename: "[name].js", 
     path: path.resolve(bundleFolder) 
    }, 
    module: { 
     rules: [{ 
      test: /\.tsx?$/, 
      loader: "ts-loader", 
      exclude: /node_modules/ 
     }, { 
      test: /\.html?$/, 
      loader: "html-loader" //TODO: file-loader? 
     }], 
     loaders: [{ 
      test: /jqxcore/, 
      loader: "imports?jquery!exports?$" 
     }, { 
      test: /jqxsplitter/, 
      loader: "imports?jquery,jqxcore!exports?$" 
     }] 
    }, 
    resolve: { 
     extensions: [".tsx", ".ts", ".js"], 
     alias: { 
      "jqxcore": "jqwidgets-framework/jqwidgets/jqxcore", 
      "jqxsplitter": "jqwidgets-framework/jqwidgets/jqxsplitter" 
     } 
    }, 
    plugins: [ 
     new CleanWebpackPlugin([bundleFolder]), 
     new HtmlWebpackPlugin({ 
      filename: "index.html", 
      template: appFolder + "index.html", 
      chunks: ["main", "vendor"] 
     }), 
     new webpack.optimize.CommonsChunkPlugin({ 
      name: "vendor", 
      filename: "vendors.js", 
      minChunks: Infinity 
     }) 
    ], 
    devtool: "source-map" 
}; 

den relevanten Teil (ich nehme an) sein

module: { 
    loaders: [{ 
     test: /jqxcore/, 
     loader: "imports?jquery!exports?$" 
    }, { 
     test: /jqxsplitter/, 
     loader: "imports?jquery,jqxcore!exports?$" 
    }] 
}, 

Es ist ziemlich klar, wie die Syntax von „ Importe/Exporte "soll den" Deps "und" Exporten "von RequireJS entsprechen. Allerdings, wenn ich dies in meiner index.ts Datei (app root):

import "jqwidgets-framework/jqwidgets/jqxsplitter"; 

Ich erhalte die Fehlermeldung „jqxBaseFramework nicht definiert ist“, wenn meine Anwendung ausgeführt wird. Ich habe Verweise auf diesen Fehler in den Foren von jQWidgets gefunden, aber keine der Antworten scheint das Problem wirklich anzugehen oder Dinge wie die AOT-Kompilation einzubeziehen, was nicht auf meine Situation zutrifft, weil ich Angular nicht verwende.

Ich habe posted diese gleiche Frage auf den jQWidges Foren, aber bis jetzt keine tatsächliche Antwort (läuft jetzt zwei Wochen), nur eine einzige generische Antwort sagen, ich sollte jqxcore.js vor jqxwhateverplugin.js laden. Nun ja, das ist es, was ich mit dem Shimming erreichen will.

Irgendwelche Ideen?

Antwort

0

Nun, ich endete mit Tieftauchen und fand es selbst heraus. Hier ist die Lösung, sollte sich jemand im selben oder einem ähnlichen Boot wiederfinden.

Wenn Sie die jQWidgets-Skriptdateien jqxcore.js verschönern, sehen Sie, dass sie eine normalerweise "globale" Variable mit dem Namen "jqxBaseFramework" erstellt, die natürlich niemals nur in einem eigenen Modul verfügbar gemacht wird. Und da liegt das Problem.

Die Lösung ist diese Konfiguration zu verwenden:

module: { 
    rules: [{ 
     test: /jqxcore/, 
     use: "exports-loader?jqxBaseFramework" 
    }, { 
     test: /jqxknockout/, 
     use: ["imports-loader?jqxBaseFramework=jqxcore,ko=knockout", "exports-loader?jqxBaseFramework"] 
    }, { 
     test: /jqxsplitter/, 
     use: "imports-loader?jqxBaseFramework=jqxknockout" 
    }] 
}, 
resolve: { 
    ... 
    alias: { 
     "knockout": "knockout/build/output/knockout-latest", 
     "jqxcore": "jqwidgets-framework/jqwidgets/jqxcore", 
     "jqxknockout": "jqwidgets-framework/jqwidgets/jqxknockout", 
     "jqxsplitter": "jqwidgets-framework/jqwidgets/jqxsplitter" 
    } 
}, 

Ich denke, wenn es klickt, das alles Sinn macht. Das jqxcore-Modul exportiert nun seine jqxBaseFramework-Variable mit demselben Namen.

Ich fügte hinzu, in Knockout-Unterstützung während es. jqxknockout erwartet, dass zwei globale Variablen normal funktionieren: ko (knockout) und jqxBaseFramework. Nun sagen wir Webpack, dass, wenn jqxknockout geladen wird, es das jqxcore-Modul laden und seinen Export einer modullokalen Variable namens "jqxBaseFramework" zuweisen und das Knockout-Modul laden und seinen Export einer modullokalen Variable namens "ko ". Dies entspricht effektiv, den folgenden Code dem jqxknockout voranzutreiben.js-Skript:

var jqxBaseFramework = require("jqxcore"); 
var ko = require("knockout"); 

Das Skript kann jetzt erneut ausgeführt werden, da diese beiden Variablen gefunden werden. Ich habe den Export-Lader hinzugefügt, um die gleiche, aber jetzt verarbeitete/erweiterte jqxBaseFramework-Variable von jqxknockout zu exportieren.

jqxSplitter braucht normalerweise nur jqxCore zu arbeiten, aber ich möchte es mit Knockout immer verwenden. Anstatt also jqxBaseFramework von jqxCore für jqxSplitter zu importieren, bekomme ich es von jqxKnockout, also sind alle Teile vorhanden. So, jetzt, wenn ich diesen Code zu addieren, was Datei Ich bin in:

import "jqwidgets-framework/jqwidgets/jqxsplitter"; 

Webpack jqxknockout und seinen Export dafür benötigt, ist jqxBaseFramework, was wiederum jqxcore erfordern und KO et voilà, die ganze Sache ist wunderschön verkabelt.

Hoffe das hilft jemandem!