UNPKG

@lynx-js/rspeedy

Version:

A webpack/rspack-based frontend toolchain for Lynx

192 lines (191 loc) 11.4 kB
import { createRequire } from "node:module"; export const __rspack_esm_id = "src_plugins_dev_plugin_ts"; export const __rspack_esm_ids = [ "src_plugins_dev_plugin_ts" ]; export const __webpack_modules__ = { "./src/plugins/dev.plugin.ts" (__unused_webpack_module, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { pluginDev: ()=>pluginDev }); var external_node_path_ = __webpack_require__("node:path"); var core_ = __webpack_require__("@rsbuild/core"); var picocolors = __webpack_require__("../../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js"); var picocolors_default = /*#__PURE__*/ __webpack_require__.n(picocolors); var debug = __webpack_require__("./src/debug.ts"); function isLynx(environment) { const environmentName = 'string' == typeof environment ? environment : environment.name; return 'lynx' === environmentName || environmentName.startsWith('lynx-'); } class ProvidePlugin_ProvidePlugin { definitions; constructor(definitions){ this.definitions = definitions; } apply(compiler) { const { ProvidePlugin } = compiler.webpack; new ProvidePlugin(this.definitions).apply(compiler); } } function pluginDev(options, server) { return { name: 'lynx:rsbuild:dev', apply (config, { action }) { return 'dev' === action || 'development' === config.mode; }, async setup (api) { const hostname = server?.host ?? await findIp('v4'); let assetPrefix = options?.assetPrefix; switch(typeof assetPrefix){ case 'string': if (server?.port !== void 0) { const hasPortPlaceholder = assetPrefix.includes('<port>'); if (!hasPortPlaceholder) { const assetPrefixURL = new URL(assetPrefix); if (assetPrefixURL.port !== String(server.port)) { core_.logger.warn(`Setting different port values in ${picocolors_default().cyan('server.port')} and ${picocolors_default().cyan('dev.assetPrefix')}. Using server.port(${picocolors_default().cyan(server.port)}) to make HMR work.`); assetPrefixURL.port = String(server.port); assetPrefix = assetPrefixURL.toString(); } } } break; case 'undefined': case 'boolean': if (options?.assetPrefix !== false) assetPrefix = `http://${hostname}:<port>/`; break; } if (server?.base) { if (assetPrefix.endsWith('/')) assetPrefix = assetPrefix.slice(0, -1); assetPrefix = `${assetPrefix}${server.base}/`; } (0, debug.Yz)(`dev.assetPrefix is normalized to ${assetPrefix}`); api.onBeforeStartDevServer(async ({ environments, server })=>{ if (environments['web']) { const { createWebVirtualFilesMiddleware } = await import("@lynx-js/web-rsbuild-server-middleware"); server.middlewares.use(createWebVirtualFilesMiddleware('/__web_preview')); } }); api.modifyRsbuildConfig((config, { mergeRsbuildConfig })=>mergeRsbuildConfig(config, { dev: { assetPrefix, client: { host: hostname, port: '<port>' } }, output: { assetPrefix } })); api.modifyRsbuildConfig((config, { mergeRsbuildConfig })=>{ const rspeedyAPIs = api.useExposed(Symbol.for('rspeedy.api')); const defaultFilename = '[name].[platform].bundle'; const { filename } = rspeedyAPIs.config.output ?? {}; let name; name = filename ? 'object' == typeof filename ? filename.bundle ?? filename.template ?? defaultFilename : filename : defaultFilename; if (config.server?.printUrls === void 0 || config.server?.printUrls === true) { const environmentNames = Object.keys(config.environments ?? {}); return mergeRsbuildConfig(config, { server: { printUrls: (param)=>{ const finalUrls = []; const baseForUrls = ('string' == typeof assetPrefix ? assetPrefix : `http://${hostname}:<port>/`).replaceAll('<port>', String(param.port)); for (const entry of Object.keys(config.source?.entry ?? {}))for (const environmentName of environmentNames){ const pathname = name.replaceAll('[name]', entry).replaceAll('[platform]', environmentName); finalUrls.push({ label: environmentName, url: new URL(pathname, baseForUrls).toString() }); if ('web' === environmentName) finalUrls.push({ label: "Web Preview", url: new URL(`/__web_preview?casename=${encodeURIComponent(pathname)}`, baseForUrls).toString() }); } return finalUrls.map((urlInfo)=>{ const label = urlInfo.label.charAt(0).toUpperCase() + urlInfo.label.slice(1); urlInfo.label = label; return urlInfo; }); } } }); } return config; }); const require = createRequire(import.meta.url); api.modifyBundlerChain((chain, { isDev, environment })=>{ const { action } = api.context; if ('dev' !== action && !isDev) return; const rsbuildPath = require.resolve('@rsbuild/core'); const rspeedyDir = external_node_path_["default"].dirname(require.resolve('@lynx-js/rspeedy/package.json')); const searchParams = new URLSearchParams({ hostname, port: api.context.devServer?.port?.toString() ?? '', pathname: '/rsbuild-hmr', hot: environment.config.dev?.hmr ?? true ? 'true' : 'false', 'live-reload': environment.config.dev?.liveReload ?? true ? 'true' : 'false', protocol: 'ws' }); if (environment.webSocketToken) searchParams.set('token', environment.webSocketToken); chain.resolve.alias.set('webpack/hot/log.js', require.resolve('@rspack/core/hot/log', { paths: [ rsbuildPath ] })).set('webpack/hot/emitter.js', require.resolve('@rspack/core/hot/emitter', { paths: [ rsbuildPath ] })).set('@lynx-js/webpack-dev-transport/client', `${require.resolve('@lynx-js/webpack-dev-transport/client')}?${searchParams.toString()}`).set('@rspack/core/hot/dev-server', require.resolve('@rspack/core/hot/dev-server', { paths: [ rsbuildPath ] })).end().end().plugin('lynx.hmr.provide.dev_server_client').use(ProvidePlugin_ProvidePlugin, [ { __webpack_dev_server_client__: [ require.resolve('./client/hmr/WebSocketClient.js', { paths: [ rspeedyDir ] }), 'default' ] } ]).end(); if (isLynx(environment)) chain.plugin('lynx.hmr.provide.websocket').use(ProvidePlugin_ProvidePlugin, [ { WebSocket: [ options?.client?.websocketTransport ?? require.resolve('@lynx-js/websocket'), 'default' ] } ]).end(); }); } }; } async function findIp(family, isInternal = false) { const [{ default: ipaddr }, os] = await Promise.all([ __webpack_require__.e("vendors-node_modules_pnpm_ipaddr_js_2_3_0_node_modules_ipaddr_js_lib_ipaddr_js").then(__webpack_require__.t.bind(__webpack_require__, "../../../node_modules/.pnpm/ipaddr.js@2.3.0/node_modules/ipaddr.js/lib/ipaddr.js", 23)), import("node:os") ]); let host; const networks = Object.values(os.networkInterfaces()).flatMap((networks)=>networks ?? []).filter((network)=>{ if (!network || !network.address) return false; if (network.family !== `IP${family}`) return false; if (network.internal !== isInternal) return false; if ('v6' === family) { const range = ipaddr.parse(network.address).range(); if ('ipv4Mapped' !== range && 'uniqueLocal' !== range) return false; } return network.address; }); if (networks.length > 0) { host = networks[0].address; if (host.includes(':')) host = `[${host}]`; } if (!host) throw new Error("No valid IP found"); return host; } } };