import { Plugin, Compiler, BannerPlugin, DefinePlugin } from 'webpack'; import { setEnvironment, getDefineVariables, getVariables } from './helpers'; const pluginName = 'PiletWebpackPlugin'; export interface PiletWebpackPluginOptions { /** * The name of the pilet. */ name: string; /** * The version of the pilet. */ version: string; /** * The name of the Piral instance / app shell. */ piral: string; /** * The schema version. By default, v1 is used. */ schema?: 'v0' | 'v1'; /** * The shared dependencies. By default, these are read from the * Piral instance. */ externals?: Array; /** * Additional environment variables to define. */ variables?: Record; } function getExternals(piral: string) { const shellPkg = require(`${piral}/package.json`); const piralExternals = shellPkg.pilets?.externals ?? []; return [ ...piralExternals, '@dbeining/react-atom', '@libre/atom', 'history', 'react', 'react-dom', 'react-router', 'react-router-dom', 'tslib', 'path-to-regexp', ]; } export class PiletWebpackPlugin implements Plugin { constructor(private options: PiletWebpackPluginOptions) {} apply(compiler: Compiler) { const environment = process.env.NODE_ENV || 'development'; const { name, version, piral, externals = getExternals(piral), schema } = this.options; const shortName = name.replace(/\W/gi, ''); const jsonpFunction = `pr_${shortName}`; const bannerSuffix = schema ? `1(${jsonpFunction})` : `0`; const variables = { ...getVariables(name, version, environment), ...this.options.variables, }; const plugins = [ new BannerPlugin({ banner: `//@pilet v:${bannerSuffix}`, entryOnly: true, raw: true, }), new DefinePlugin(getDefineVariables(variables)), ]; setEnvironment(variables); plugins.forEach(plugin => plugin.apply(compiler)); compiler.hooks.afterEnvironment.tap(pluginName, () => { const current = compiler.options.externals; compiler.options.output.jsonpFunction = `${jsonpFunction}_chunks`; compiler.options.output.libraryTarget = 'umd'; compiler.options.output.library = name; if (schema === 'v1') { compiler.options.output.auxiliaryComment = { commonjs2: `\nfunction define(d,k){(typeof document!=='undefined')&&(document.currentScript.app=k.apply(null,d.map(window.${jsonpFunction})));}define.amd=!0;`, } as any; } compiler.options.externals = Array.isArray(current) ? [...current, ...externals] : current ? [current, ...externals] : externals; }); } }