Skip to content
This repository has been archived by the owner on Feb 4, 2022. It is now read-only.

Commit

Permalink
Adjusted for v2 schema
Browse files Browse the repository at this point in the history
  • Loading branch information
FlorianRappl committed Sep 10, 2021
1 parent 4fc982a commit 8e9061b
Show file tree
Hide file tree
Showing 10 changed files with 212 additions and 123 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[![Piral Logo](https://github.com/smapiot/piral/raw/master/docs/assets/logo.png)](https://piral.io)
[![Piral Logo](https://github.com/smapiot/piral/raw/main/docs/assets/logo.png)](https://piral.io)

# Piral Webpack Tools

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"lerna": "^3.13.0",
"prettier": "^1.16.4",
"ts-jest": "^25.0.0",
"typescript": "^3.8.3"
"typescript": "^4.4.3"
},
"resolutions": {
"node-notifier": "8.0.1"
Expand Down
7 changes: 3 additions & 4 deletions packages/html5-entry-webpack-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@
"webpack": "4.42.0"
},
"dependencies": {
"cheerio": "^1.0.0-rc.3",
"html-webpack-plugin": "^4.2.0"
},
"gitHead": "d8766113afb41e6962a01b71121403c979d5a803"
"cheerio": "^1.0.0-rc.10",
"html-webpack-plugin": "^4.5.2"
}
}
3 changes: 1 addition & 2 deletions packages/parcel-codegen-loader/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,5 @@
"dependencies": {
"loader-utils": "^2.0.0",
"schema-utils": "^2.6.5"
},
"gitHead": "d8766113afb41e6962a01b71121403c979d5a803"
}
}
3 changes: 1 addition & 2 deletions packages/pilet-webpack-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,5 @@
"homepage": "https://github.com/FlorianRappl/piral-webpack-tools#readme",
"devDependencies": {
"webpack": "4.42.0"
},
"gitHead": "d8766113afb41e6962a01b71121403c979d5a803"
}
}
56 changes: 56 additions & 0 deletions packages/pilet-webpack-plugin/src/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { Configuration } from 'webpack';
import { SharedDependency } from './types';

export function getVariables(name: string, version: string, env: string): Record<string, string> {
return {
NODE_ENV: env,
Expand All @@ -18,3 +21,56 @@ export function getDefineVariables(variables: Record<string, string>) {
return obj;
}, {});
}

export 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 function getDependencies(importmap: Array<SharedDependency>, compilerOptions: Configuration) {
const dependencies = {};

if (typeof compilerOptions.entry === 'object' && compilerOptions.entry) {
for (const dep of importmap) {
dependencies[dep.id] = dep.ref;
compilerOptions.externals[dep.name] = dep.id;

if (dep.type === 'local') {
compilerOptions.entry[dep.ref.replace(/\.js$/, '')] = dep.entry;
}
}
}

return dependencies;
}

export function withExternals(compilerOptions: Configuration, externals: Array<string>) {
const current = compilerOptions.externals;
const newExternals = Array.isArray(current)
? [...(current as Array<string>), ...externals]
: typeof current === 'string'
? [current, ...externals]
: externals;

if (newExternals !== externals || typeof compilerOptions.externals !== 'object' || !compilerOptions.externals) {
compilerOptions.externals = {};
}

for (const external of newExternals) {
if (typeof external === 'string') {
compilerOptions.externals[external] = external;
}
}
}
190 changes: 101 additions & 89 deletions packages/pilet-webpack-plugin/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,107 +1,119 @@
import { Plugin, Compiler, BannerPlugin, DefinePlugin } from 'webpack';
import { setEnvironment, getDefineVariables, getVariables } from './helpers';
import {
setEnvironment,
getDefineVariables,
getVariables,
getExternals,
withExternals,
getDependencies,
} from './helpers';
import { PiletWebpackPluginOptions } from './types';

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' | 'none';
/**
* The shared dependencies. By default, these are read from the
* Piral instance.
*/
externals?: Array<string>;
/**
* Additional environment variables to define.
*/
variables?: Record<string, string>;
}
export class PiletWebpackPlugin implements Plugin {
private variables: Record<string, string>;
private externals: Array<string>;

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',
];
}
constructor(private options: PiletWebpackPluginOptions) {}

export class PiletWebpackPlugin implements Plugin {
constructor(private options: PiletWebpackPluginOptions) { }
piletVxWebpackConfigEnhancer(compiler: Compiler) {
const config = compiler.options;

apply(compiler: Compiler) {
const environment = process.env.NODE_ENV || 'development';
const { name, version, piral, externals = getExternals(piral), schema } = this.options;
setEnvironment(this.variables);
withExternals(config, this.externals);

const plugins = [new DefinePlugin(getDefineVariables(this.variables))];
compiler.hooks.afterEnvironment.tap(pluginName, () => {});
return plugins;
}

piletV1WebpackConfigEnhancer(compiler: Compiler) {
const { name } = this.options;
const config = compiler.options;
const shortName = name.replace(/\W/gi, '');
const jsonpFunction = `pr_${shortName}`;
const variables = {
...getVariables(name, version, environment),
...this.options.variables,
};
const prName = `wp4Chunkpr_${shortName}`;
const [mainEntry] = Object.keys(config.entry);

setEnvironment(this.variables);
withExternals(config, this.externals);

const plugins = [
new DefinePlugin(getDefineVariables(variables)),
new DefinePlugin(getDefineVariables(this.variables)),
new BannerPlugin({
banner: `//@pilet v:1(${prName})`,
entryOnly: true,
include: `${mainEntry}.js`,
raw: true,
}),
];

if (schema !== 'none') {
const bannerSuffix = schema === 'v1' ? `1(${jsonpFunction})` : `0`;

plugins.push(
new BannerPlugin({
banner: `//@pilet v:${bannerSuffix}`,
entryOnly: true,
include: /\.js$/,
raw: true,
}),
);
}
compiler.hooks.afterEnvironment.tap(pluginName, () => {
config.output.jsonpFunction = `${prName}`;
config.output.library = name;
config.output.libraryTarget = 'umd';
config.output.auxiliaryComment = {
commonjs2: `\nfunction define(d,k){if(typeof document!=='undefined'){var _r=${prName};delete ${prName};document.currentScript.app=k.apply(null,d.map(_r))}}define.amd=!0;`,
} as any;
});

setEnvironment(variables);
return plugins;
}

plugins.forEach(plugin => plugin.apply(compiler));
piletV2WebpackConfigEnhancer(compiler: Compiler) {
const { name, importmap } = this.options;
const config = compiler.options;
const shortName = name.replace(/\W/gi, '');
const prName = `wp4Chunkpr_${shortName}`;
const [mainEntry] = Object.keys(config.entry);

withExternals(config, this.externals);
setEnvironment(this.variables);

const dependencies = getDependencies(importmap, config);

const plugins = [
new DefinePlugin(getDefineVariables(this.variables)),
new BannerPlugin({
banner: `//@pilet v:2(${prName},${JSON.stringify(dependencies)})`,
entryOnly: true,
include: `${mainEntry}.js`,
raw: true,
}),
];

compiler.hooks.afterEnvironment.tap(pluginName, () => {
const current = compiler.options.externals;
compiler.options.output.jsonpFunction = `${jsonpFunction}_chunks`;
compiler.options.output.library = name;

if (schema !== 'none') {
compiler.options.output.libraryTarget = 'umd';
}

if (schema === 'v1') {
const reset = environment !== 'production' ? `delete ${jsonpFunction}_chunks;` : '';
compiler.options.output.auxiliaryComment = {
commonjs2: `\nfunction define(d,k){${reset}(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;
config.module.rules.push({ parser: { system: false } });
config.output.jsonpFunction = `${prName}`;
config.output.libraryTarget = 'system';
});

return plugins;
}

setup(compiler: Compiler) {
const { name, version, piral, externals = getExternals(piral), schema } = this.options;
const environment = process.env.NODE_ENV || 'development';
this.variables = {
...getVariables(name, version, environment),
...this.options.variables,
};
this.externals = externals;

switch (schema) {
case 'v1':
return this.piletV1WebpackConfigEnhancer(compiler);
case 'v2':
return this.piletV2WebpackConfigEnhancer(compiler);
case 'v0':
case 'none':
default:
return this.piletVxWebpackConfigEnhancer(compiler);
}
}

apply(compiler: Compiler) {
const plugins = this.setup(compiler);
plugins.forEach(plugin => plugin.apply(compiler));
}
}
39 changes: 39 additions & 0 deletions packages/pilet-webpack-plugin/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
export interface SharedDependency {
id: string;
name: string;
ref: string;
type: 'local' | 'remote';
entry: string;
}

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' | 'v2' | 'none';
/**
* The shared dependencies. By default, these are read from the
* Piral instance.
*/
externals?: Array<string>;
/**
* Additional environment variables to define.
*/
variables?: Record<string, string>;
/**
* The shared dependencies to consider.
*/
importmap?: Array<SharedDependency>;
}
3 changes: 1 addition & 2 deletions packages/piral-instance-webpack-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,5 @@
"homepage": "https://github.com/FlorianRappl/piral-webpack-tools#readme",
"devDependencies": {
"webpack": "4.42.0"
},
"gitHead": "d8766113afb41e6962a01b71121403c979d5a803"
}
}
Loading

0 comments on commit 8e9061b

Please sign in to comment.