J'essaie d'utiliser web pack pour compiler une chaîne en mémoire de code javascript valide. J'utilise memory fs comme indiqué ici : https://webpack.github.io/docs/node.js-api.html#compile-to-memory .
Donc, je prends une chaîne contenant du javascript brut, je l'écris dans le fs mémoire, et ensuite le pack web se résout à ce point d'entrée. Mais la compilation échoue à la première instruction require, sans doute parce qu'elle n'est pas capable de rechercher les node_modules dans le vrai fs.
Avez-vous une idée de la façon dont je peux y parvenir ?
import webpack from 'webpack';
import MemoryFS from 'memory-fs';
import thenify from 'thenify';
function* compile(code) {
const fs = new MemoryFS();
fs.writeFileSync('/file.js', code);
const compiler = webpack({
entry: { file: '/file.js' },
output: {
path: '/build',
filename: '[name].js'
},
module: {
loaders: [
{ test: /\.json$/, loader: 'json' }
],
}
});
compiler.run = thenify(compiler.run);
compiler.inputFileSystem = fs;
compiler.resolvers.normal.fileSystem = fs; //this is needed for memfs
compiler.outputFileSystem = fs;
const stats = yield compiler.run();
//retrieve the output of the compilation
const res = stats.compilation.assets['file.js'].source();
return res;
}
Utilisation
var code = "var _ = require('underscore'); console.log(_);";
var bundle = yield compile(code); //should be a bundle containing the underscore source.
L'erreur est
ModuleNotFoundError : Module non trouvé : Erreur : Impossible de résoudre le module underscore dans /
Cette question indique que d'autres ont essayé la même chose : https://github.com/webpack/webpack/issues/1562 . il y a un résumé référencé à https://gist.github.com/DatenMetzgerX/2a96ebf287b4311f4c18 qui, je crois, était destiné à faire ce que j'espère accomplir, mais dans sa forme actuelle, je ne vois pas comment. Il assigne une instance de MemoryFs à tous les résolveurs. J'ai essayé d'assigner le module fs du noeud, mais sans succès.
En résumé, j'essaie de définir un point d'entrée vers une chaîne en mémoire de javascript brut, tout en ayant les instructions require et import résolues vers les node_modules sur le disque.
UPDATE
J'ai réussi à obtenir le résultat que je recherche, mais ce n'est pas joli. Je suis en train de remplacer l'implémentation de #stat et #readFile dans MemoryFS pour vérifier le système de fichiers réel s'il reçoit une demande pour un fichier qui n'existe pas en mémoire. Je pourrais nettoyer un peu cela en sous-classant MemoryFS au lieu de permuter les implémentations des méthodes au moment de l'exécution, mais l'idée serait toujours la même.
Solution de travail
import webpack from 'webpack';
import JsonLoader from 'json-loader';
import MemoryFS from 'memory-fs';
import UglifyJS from "uglify-js";
import thenify from 'thenify';
import path from 'path';
import fs from 'fs';
import root from 'app-root-path';
/*
* Provide webpack with an instance of MemoryFS for
* in-memory compilation. We're currently overriding
* #stat and #readFile. Webpack will ask MemoryFS for the
* entry file, which it will find successfully. However,
* all dependencies are on the real filesystem, so any require
* or import statements will fail. When that happens, our wrapper
* functions will then check fs for the requested file.
*/
const memFs = new MemoryFS();
const statOrig = memFs.stat.bind(memFs);
const readFileOrig = memFs.readFile.bind(memFs);
memFs.stat = function (_path, cb) {
statOrig(_path, function(err, result) {
if (err) {
return fs.stat(_path, cb);
} else {
return cb(err, result);
}
});
};
memFs.readFile = function (path, cb) {
readFileOrig(path, function (err, result) {
if (err) {
return fs.readFile(path, cb);
} else {
return cb(err, result);
}
});
};
export default function* compile(code) {
// Setup webpack
//create a directory structure in MemoryFS that matches
//the real filesystem
const rootDir = root.toString();
//write code snippet to memoryfs
const outputName = `file.js`;
const entry = path.join(rootDir, outputName);
const rootExists = memFs.existsSync(rootDir);
if (!rootExists) {
memFs.mkdirpSync(rootDir);
}
memFs.writeFileSync(entry, code);
//point webpack to memoryfs for the entry file
const compiler = webpack({
entry: entry,
output: {
filename: outputName
},
module: {
loaders: [
{ test: /\.json$/, loader: 'json' }
]
}
});
compiler.run = thenify(compiler.run);
//direct webpack to use memoryfs for file input
compiler.inputFileSystem = memFs;
compiler.resolvers.normal.fileSystem = memFs;
//direct webpack to output to memoryfs rather than to disk
compiler.outputFileSystem = memFs;
const stats = yield compiler.run();
//remove entry from memory. we're done with it
memFs.unlinkSync(entry);
const errors = stats.compilation.errors;
if (errors && errors.length > 0) {
//if there are errors, throw the first one
throw errors[0];
}
//retrieve the output of the compilation
const res = stats.compilation.assets[outputName].source();
return res;
}
Utilisation
var code = "var _ = require('underscore'); console.log(_);";
var bundle = yield compile(code); //is a valid js bundle containing the underscore source and a log statement logging _.
S'il n'y a pas de meilleur moyen, alors je vais certainement encapsuler ceci dans une sous-classe de MemoryFS, mais j'espère qu'il y a un moyen plus sain d'accomplir ceci avec l'api de Webpack.
2 votes
Pouvez-vous montrer un code plus complet, y compris votre
require
déclarations ?0 votes
@jonaz J'ai mis à jour le snippet original et j'ai également ajouté une nouvelle version que j'ai réussi à faire fonctionner. J'espère trouver une meilleure solution.
0 votes
Pouvez-vous donner plus d'informations sur les exigences d'origine ? On dirait que vous voulez un point d'entrée dynamique ?
0 votes
htmlwebpackplugin
apporte aussi plus d'erreurs, donc quand mon Root enmemory-fs
es/src
le plugin essaie d'accéder àC:\src
ce qui échoue. J'ai donc ajouté ceci à l'écrasement du fichier de lecture :if(_path.includes('C:\\src')) { _path = _path.substring(2) _path = _path.replace(/\\/g, '/') }