@wii/fastify-webpack
Version:
fastify plugin for webpack
115 lines (112 loc) • 4.01 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
require("core-js/modules/es.promise.js");
require("core-js/modules/es.array.iterator.js");
require("core-js/modules/web.dom-collections.iterator.js");
var _nodeEvents = _interopRequireDefault(require("node:events"));
var _nodePath = _interopRequireDefault(require("node:path"));
var _fastifyPlugin = _interopRequireDefault(require("fastify-plugin"));
var _memfs = require("memfs");
var _mimeTypes = _interopRequireDefault(require("mime-types"));
var _negotiator = _interopRequireDefault(require("negotiator"));
var _utils = require("./utils");
const MODULE_NAME = 'FASTIFY_WEBPACK';
/**
* Compiler watch options
* copied from webpack
*/
const fastifyWebpack = (0, _fastifyPlugin.default)(async (fastify, {
compiler,
outputFileSystem = (0, _memfs.createFsFromVolume)(new _memfs.Volume()),
watchOptions,
path: urlPath = '/__fastify_webpack_hot'
}) => {
const eventEmitter = new _nodeEvents.default();
compiler.outputFileSystem = outputFileSystem;
let statsPromise = (0, _utils.defer)();
compiler.hooks.watchRun.tap(MODULE_NAME, () => {
if (statsPromise.resolved) {
statsPromise = (0, _utils.defer)();
}
if (compiler.modifiedFiles) {
const modifiedFiles = Array.from(compiler.modifiedFiles);
fastify.log.info(modifiedFiles, 'building a webpack bundle');
} else {
fastify.log.info('building a webpack bundle');
}
});
const watcher = compiler.watch({
aggregateTimeout: 500,
poll: false,
...watchOptions
}, (err, stats) => {
if (err) {
fastify.log.error(err);
} else if (stats) {
statsPromise.resolve(stats);
const syncEvents = (0, _utils.createSyncEvents)(stats);
for (const syncEvent of syncEvents) {
eventEmitter.emit('sync', syncEvent);
}
}
});
fastify.get(urlPath, (request, reply) => {
const headers = {
'cache-control': 'no-store',
'content-type': 'text/event-stream'
};
reply.raw.writeHead(200, headers);
const sync = event => {
reply.raw.write((0, _utils.formatServerEvent)('sync', event));
};
eventEmitter.addListener('sync', sync);
request.raw.on('close', () => {
eventEmitter.removeListener('sync', sync);
});
});
fastify.addHook('onRequest', async (request, reply) => {
reply.webpack = {
outputFileSystem
};
if (request.method !== 'GET' && request.method !== 'HEAD') {
return;
}
if (!statsPromise.resolved) {
fastify.log.info('waiting for the compiler to finish bundling');
}
const stats = await statsPromise.promise;
reply.webpack = {
outputFileSystem,
stats
};
const fileName = await (0, _utils.getFilenameFromUrl)(fastify, outputFileSystem, stats, request.url);
if (fileName) {
const contentType = _mimeTypes.default.contentType(_nodePath.default.extname(fileName));
if (contentType) {
reply.header('content-type', contentType);
}
const negotiator = new _negotiator.default(request.raw);
const encodings = negotiator.encodings();
if (encodings.includes('br') && (await (0, _utils.canRead)(outputFileSystem, fileName + '.br'))) {
reply.header('content-encoding', 'br');
return reply.send(await outputFileSystem.promises.readFile(fileName + '.br'));
} else if (encodings.includes('gzip') && (await (0, _utils.canRead)(outputFileSystem, fileName + '.gz'))) {
reply.header('content-encoding', 'gzip');
return reply.send(await outputFileSystem.promises.readFile(fileName + '.gz'));
} else {
return reply.send(await outputFileSystem.promises.readFile(fileName));
}
}
});
fastify.addHook('onClose', (instance, done) => {
watcher.close(() => {
done();
});
});
});
var _default = fastifyWebpack;
exports.default = _default;