UNPKG

@wii/fastify-webpack

Version:

fastify plugin for webpack

115 lines (112 loc) 4.01 kB
"use strict"; 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;