2020-12-04 21:15:41 +08:00
|
|
|
// Copyright (c) Jupyter Development Team.
|
|
|
|
// Distributed under the terms of the Modified BSD License.
|
|
|
|
|
|
|
|
// Heavily inspired (and slightly tweaked) from:
|
|
|
|
// https://github.com/jupyterlab/jupyterlab/blob/master/examples/federated/core_package/webpack.config.js
|
|
|
|
|
|
|
|
const fs = require('fs-extra');
|
|
|
|
const path = require('path');
|
|
|
|
const webpack = require('webpack');
|
|
|
|
const merge = require('webpack-merge').default;
|
|
|
|
const { ModuleFederationPlugin } = webpack.container;
|
|
|
|
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
|
|
|
|
.BundleAnalyzerPlugin;
|
|
|
|
|
|
|
|
const Build = require('@jupyterlab/builder').Build;
|
|
|
|
const baseConfig = require('@jupyterlab/builder/lib/webpack.config.base');
|
|
|
|
|
|
|
|
const data = require('./package.json');
|
|
|
|
|
|
|
|
const names = Object.keys(data.dependencies).filter(name => {
|
|
|
|
const packageData = require(path.join(name, 'package.json'));
|
|
|
|
return packageData.jupyterlab !== undefined;
|
|
|
|
});
|
|
|
|
|
|
|
|
// Ensure a clear build directory.
|
|
|
|
const buildDir = path.resolve(__dirname, 'build');
|
|
|
|
if (fs.existsSync(buildDir)) {
|
|
|
|
fs.removeSync(buildDir);
|
|
|
|
}
|
|
|
|
fs.ensureDirSync(buildDir);
|
|
|
|
|
|
|
|
// Copy extra files
|
|
|
|
const index = path.resolve(__dirname, 'index.js');
|
2020-12-10 07:47:58 +08:00
|
|
|
const cssImports = path.resolve(__dirname, 'style.js');
|
2020-12-04 21:15:41 +08:00
|
|
|
fs.copySync(index, path.resolve(buildDir, 'index.js'));
|
2021-02-19 16:25:59 +08:00
|
|
|
fs.copySync(cssImports, path.resolve(buildDir, 'extraStyle.js'));
|
2020-12-04 21:15:41 +08:00
|
|
|
|
|
|
|
const extras = Build.ensureAssets({
|
|
|
|
packageNames: names,
|
|
|
|
output: buildDir
|
|
|
|
});
|
|
|
|
|
2021-02-19 16:25:59 +08:00
|
|
|
/**
|
|
|
|
* Create the webpack ``shared`` configuration
|
|
|
|
*/
|
|
|
|
function createShared(packageData) {
|
|
|
|
// Set up module federation sharing config
|
|
|
|
const shared = {};
|
|
|
|
const extensionPackages = packageData.jupyterlab.extensions;
|
|
|
|
|
|
|
|
// Make sure any resolutions are shared
|
|
|
|
for (let [pkg, requiredVersion] of Object.entries(packageData.resolutions)) {
|
|
|
|
shared[pkg] = { requiredVersion };
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add any extension packages that are not in resolutions (i.e., installed from npm)
|
|
|
|
for (let pkg of extensionPackages) {
|
|
|
|
if (!shared[pkg]) {
|
|
|
|
shared[pkg] = {
|
|
|
|
requiredVersion: require(`${pkg}/package.json`).version
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add dependencies and sharedPackage config from extension packages if they
|
|
|
|
// are not already in the shared config. This means that if there is a
|
|
|
|
// conflict, the resolutions package version is the one that is shared.
|
|
|
|
const extraShared = [];
|
|
|
|
for (let pkg of extensionPackages) {
|
|
|
|
let pkgShared = {};
|
|
|
|
let {
|
|
|
|
dependencies = {},
|
|
|
|
jupyterlab: { sharedPackages = {} } = {}
|
|
|
|
} = require(`${pkg}/package.json`);
|
|
|
|
for (let [dep, requiredVersion] of Object.entries(dependencies)) {
|
|
|
|
if (!shared[dep]) {
|
|
|
|
pkgShared[dep] = { requiredVersion };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Overwrite automatic dependency sharing with custom sharing config
|
|
|
|
for (let [dep, config] of Object.entries(sharedPackages)) {
|
|
|
|
if (config === false) {
|
|
|
|
delete pkgShared[dep];
|
|
|
|
} else {
|
|
|
|
if ('bundled' in config) {
|
|
|
|
config.import = config.bundled;
|
|
|
|
delete config.bundled;
|
|
|
|
}
|
|
|
|
pkgShared[dep] = config;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
extraShared.push(pkgShared);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now merge the extra shared config
|
|
|
|
const mergedShare = {};
|
|
|
|
for (let sharedConfig of extraShared) {
|
|
|
|
for (let [pkg, config] of Object.entries(sharedConfig)) {
|
|
|
|
// Do not override the basic share config from resolutions
|
|
|
|
if (shared[pkg]) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add if we haven't seen the config before
|
|
|
|
if (!mergedShare[pkg]) {
|
|
|
|
mergedShare[pkg] = config;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Choose between the existing config and this new config. We do not try
|
|
|
|
// to merge configs, which may yield a config no one wants
|
|
|
|
let oldConfig = mergedShare[pkg];
|
|
|
|
|
|
|
|
// if the old one has import: false, use the new one
|
|
|
|
if (oldConfig.import === false) {
|
|
|
|
mergedShare[pkg] = config;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Object.assign(shared, mergedShare);
|
|
|
|
|
|
|
|
// Transform any file:// requiredVersion to the version number from the
|
|
|
|
// imported package. This assumes (for simplicity) that the version we get
|
|
|
|
// importing was installed from the file.
|
|
|
|
for (let [pkg, { requiredVersion }] of Object.entries(shared)) {
|
|
|
|
if (requiredVersion && requiredVersion.startsWith('file:')) {
|
|
|
|
shared[pkg].requiredVersion = require(`${pkg}/package.json`).version;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add singleton package information
|
|
|
|
for (let pkg of packageData.jupyterlab.singletonPackages) {
|
|
|
|
if (shared[pkg]) {
|
|
|
|
shared[pkg].singleton = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return shared;
|
|
|
|
}
|
2020-12-04 21:15:41 +08:00
|
|
|
|
|
|
|
// Make a bootstrap entrypoint
|
|
|
|
const entryPoint = path.join(buildDir, 'bootstrap.js');
|
|
|
|
const bootstrap = 'import("./index.js");';
|
|
|
|
fs.writeFileSync(entryPoint, bootstrap);
|
|
|
|
|
|
|
|
if (process.env.NODE_ENV === 'production') {
|
|
|
|
baseConfig.mode = 'production';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (process.argv.includes('--analyze')) {
|
|
|
|
extras.push(new BundleAnalyzerPlugin());
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = [
|
|
|
|
merge(baseConfig, {
|
|
|
|
mode: 'development',
|
|
|
|
entry: ['./publicpath.js', './' + path.relative(__dirname, entryPoint)],
|
|
|
|
output: {
|
2021-05-19 21:13:00 +08:00
|
|
|
path: path.resolve(__dirname, '..', 'retrolab/static/'),
|
2020-12-04 21:15:41 +08:00
|
|
|
library: {
|
|
|
|
type: 'var',
|
|
|
|
name: ['_JUPYTERLAB', 'CORE_OUTPUT']
|
|
|
|
},
|
|
|
|
filename: 'bundle.js'
|
|
|
|
},
|
|
|
|
plugins: [
|
|
|
|
new ModuleFederationPlugin({
|
|
|
|
library: {
|
|
|
|
type: 'var',
|
|
|
|
name: ['_JUPYTERLAB', 'CORE_LIBRARY_FEDERATION']
|
|
|
|
},
|
|
|
|
name: 'CORE_FEDERATION',
|
2021-02-19 16:25:59 +08:00
|
|
|
shared: createShared(data)
|
2020-12-04 21:15:41 +08:00
|
|
|
})
|
|
|
|
]
|
|
|
|
})
|
|
|
|
].concat(extras);
|