Tôi đang cố gắng sử dụng gói web để biên dịch một chuỗi bộ nhớ của mã javascript hợp lệ. Tôi đang sử dụng bộ nhớ fs như được nêu ở đây: https://webpack.github.io/docs/node.js-api.html#compile-to-memory.Biên dịch Webpack trong bộ nhớ nhưng phân giải thành node_modules trên đĩa
Vì vậy, tôi đang dùng một chuỗi chứa javascript thô, viết nó vào bộ nhớ fs và sau đó gói web phân giải tới điểm nhập đó. Nhưng trình biên dịch không thành công trên câu lệnh require đầu tiên, có lẽ vì nó không thể nhìn vào fs thực cho node_modules.
Bất kỳ ý tưởng nào về cách tôi có thể thực hiện việc này?
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;
}
Cách sử dụng
var code = "var _ = require('underscore'); console.log(_);";
var bundle = yield compile(code); //should be a bundle containing the underscore source.
Lỗi này là
ModuleNotFoundError: Module not found: Error: Cannot resolve module underscore in /
Câu hỏi này chỉ ra rằng những người khác đã cố gắng điều tương tự: https://github.com/webpack/webpack/issues/1562. có một ý chính được tham chiếu tại số https://gist.github.com/DatenMetzgerX/2a96ebf287b4311f4c18 mà tôi tin là có ý định làm những gì tôi hy vọng đạt được, nhưng ở dạng hiện tại tôi không thấy như thế nào. Nó gán một thể hiện của MemoryFs cho tất cả các trình phân giải. Tôi đã thử gán module fs của nút, nhưng không có con xúc xắc.
Vì vậy, trong ngắn hạn, tôi đang cố gắng thiết lập một điểm vào một chuỗi bộ nhớ của javascript thô, nhưng vẫn yêu cầu và nhập khẩu các câu lệnh được giải quyết cho node_modules trên đĩa.
CẬP NHẬT
tôi đã có thể để có được những kết quả Tôi đang tìm nhưng nó không đẹp. Tôi về cơ bản sẽ ghi đè việc triển khai #stat và #readFile trong MemoryFS để kiểm tra hệ thống tệp thực nếu nó nhận được bất kỳ yêu cầu nào đối với tệp không tồn tại trong bộ nhớ. Tôi có thể làm sạch điều này một chút bằng cách phân lớp MemoryFS thay vì hoán đổi phương thức triển khai thực hiện trong thời gian chạy, nhưng ý tưởng sẽ vẫn như cũ.
giải pháp làm việc
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;
}
Cách sử dụng
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 _.
Nếu có không phải là một cách tốt hơn, sau đó tôi chắc chắn sẽ tóm lược này thành một lớp con của MemoryFS, nhưng tôi hy vọng có một cách lành mạnh hơn để thực hiện điều này với api của Webpack.
Bạn có thể hiển thị mã hoàn thiện hơn, bao gồm cả 'báo cáo require' của bạn? – jonaz
@jonaz Tôi đã cập nhật đoạn mã gốc và cũng đã thêm một phiên bản mới mà tôi đã có thể làm việc. Hy vọng đến với một cách tốt hơn mặc dù. – mike
Bạn có thể nêu rõ thêm thông tin về yêu cầu xuất xứ không? Có vẻ như bạn muốn có một điểm vào động? –