import assert from 'assert'; import address from 'address'; import { lodash } from '@fesjs/utils'; import { readFileSync } from 'fs'; import { join } from 'path'; import { qiankunStateFromMainModelNamespace } from '../constants'; const namespace = 'plugin-qiankun/micro'; export function isSlaveEnable(api) { return !!api.userConfig?.qiankun?.micro || lodash.isEqual(api.userConfig?.qiankun, {}) || !!process.env.INITIAL_QIANKUN_MIRCO_OPTIONS; } export default function (api) { const { utils: { Mustache }, } = api; api.describe({ enableBy: () => isSlaveEnable(api), }); api.modifyDefaultConfig((memo) => { const initialMicroOptions = { devSourceMap: true, ...JSON.parse(process.env.INITIAL_QIANKUN_MIRCO_OPTIONS || '{}'), ...(memo.qiankun || {}).micro, }; const modifiedDefaultConfig = { ...memo, qiankun: { ...memo.qiankun, slave: initialMicroOptions, }, }; const shouldNotModifyDefaultBase = api.userConfig.qiankun?.slave?.shouldNotModifyDefaultBase ?? initialMicroOptions.shouldNotModifyDefaultBase; if (!shouldNotModifyDefaultBase) { modifiedDefaultConfig.base = `/${api.pkg.name}`; } return modifiedDefaultConfig; }); api.chainWebpack((config) => { assert(api.pkg.name, 'You should have name in package.json'); config.output.libraryTarget('umd').library(`${api.pkg.name}-[name]`); return config; }); const port = process.env.PORT; // source-map 跨域设置 if (process.env.NODE_ENV === 'development' && port) { const localHostname = process.env.USE_REMOTE_IP ? address.ip() : process.env.HOST || 'localhost'; const protocol = process.env.HTTPS ? 'https' : 'http'; // TODO: 变更 webpack-dev-server websocket 默认监听地址 api.chainWebpack((memo, { webpack }) => { // 开启了 devSourceMap 配置,默认为 true if (api.config.qiankun && api.config.qiankun.micro && api.config.qiankun.micro.devSourceMap !== false) { // 禁用 devtool,启用 SourceMapDevToolPlugin memo.devtool(false); memo.plugin('source-map').use(webpack.SourceMapDevToolPlugin, [ { // @ts-ignore namespace: api.pkg.name, append: `\n//# sourceMappingURL=${protocol}://${localHostname}:${port}/[url]`, filename: '[file].map', }, ]); } return memo; }); } const absRuntimePath = join(namespace, 'runtime.js'); const absLifeclesPath = join(namespace, 'lifecycles.js'); const absMicroOptionsPath = join(namespace, 'slaveOptions.js'); const absPublicPath = join(namespace, 'publicPath.js'); const absModelPath = join(namespace, 'qiankunModel.js'); // 更改public path api.addEntryImportsAhead(() => [{ source: `@@/${absPublicPath}` }]); api.register({ key: 'addExtraModels', fn: () => { if (api.hasPlugins(['@fesjs/plugin-model'])) { return [ { absPath: `@@/${absModelPath}`, namespace: qiankunStateFromMainModelNamespace, }, ]; } return []; }, }); api.onGenerateFiles(() => { const HAS_PLUGIN_MODEL = api.hasPlugins(['@fesjs/plugin-model']); api.writeTmpFile({ path: absRuntimePath, content: readFileSync(join(__dirname, 'runtime/runtime.tpl'), 'utf-8'), }); api.writeTmpFile({ path: absLifeclesPath, content: Mustache.render(readFileSync(join(__dirname, 'runtime/lifecycles.tpl'), 'utf-8'), { HAS_PLUGIN_MODEL, }), }); api.writeTmpFile({ path: absPublicPath, content: ` if (window.__POWERED_BY_QIANKUN__) { __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__; window.public_path = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__; } `, }); api.writeTmpFile({ path: absMicroOptionsPath, content: ` let options = ${JSON.stringify((api.config.qiankun || {}).micro || {})}; export const getSlaveOptions = () => options; export const setSlaveOptions = (newOpts) => options = ({ ...options, ...newOpts }); `, }); if (HAS_PLUGIN_MODEL) { api.writeTmpFile({ path: absModelPath, content: readFileSync(join(__dirname, 'runtime/qiankunModel.tpl'), 'utf-8'), }); } }); api.addRuntimePlugin(() => `@@/${absRuntimePath}`); api.addEntryImports(() => ({ source: `@@/${absLifeclesPath}`, specifier: '{ genMount as qiankun_genMount, genBootstrap as qiankun_genBootstrap, genUnmount as qiankun_genUnmount, genUpdate as qiankun_genUpdate }', })); api.addEntryCode( () => ` export const bootstrap = qiankun_genBootstrap(clientRender, app); export const mount = qiankun_genMount('#${api.config.mountElementId}'); export const unmount = qiankun_genUnmount(); export const update = qiankun_genUpdate(); if (!window.__POWERED_BY_QIANKUN__) { bootstrap().then(mount); } `, ); }