From 17ff0c0a6aaca9cad0e409dbfa3e42d3cddd25ec Mon Sep 17 00:00:00 2001 From: Jason Grout Date: Wed, 25 May 2022 13:33:04 -0600 Subject: [PATCH 1/3] Default publicPath to 'auto' The 'auto' setting should automatically choose the correct public path, depending on where the js file was loaded from. This removes the difference between the classic notebook extension bundle and the CDN bundle, so we also consolidated the two webpack targets. --- .../js/lib/embed.js | 9 -------- .../js/lib/extension.js | 6 ------ .../js/webpack.config.js | 21 +++++++------------ 3 files changed, 7 insertions(+), 29 deletions(-) delete mode 100644 {{cookiecutter.github_project_name}}/js/lib/embed.js diff --git a/{{cookiecutter.github_project_name}}/js/lib/embed.js b/{{cookiecutter.github_project_name}}/js/lib/embed.js deleted file mode 100644 index 9a4e145..0000000 --- a/{{cookiecutter.github_project_name}}/js/lib/embed.js +++ /dev/null @@ -1,9 +0,0 @@ -// Entry point for the unpkg bundle containing custom model definitions. -// -// It differs from the notebook bundle in that it does not need to define a -// dynamic baseURL for the static assets and may load some css that would -// already be loaded by the notebook otherwise. - -// Export widget models and views, and the npm package version number. -module.exports = require('./example.js'); -module.exports['version'] = require('../package.json').version; diff --git a/{{cookiecutter.github_project_name}}/js/lib/extension.js b/{{cookiecutter.github_project_name}}/js/lib/extension.js index 6166fcc..a39de14 100644 --- a/{{cookiecutter.github_project_name}}/js/lib/extension.js +++ b/{{cookiecutter.github_project_name}}/js/lib/extension.js @@ -1,12 +1,6 @@ // This file contains the javascript that is run when the notebook is loaded. // It contains some requirejs configuration and the `load_ipython_extension` // which is required for any notebook extension. -// -// Some static assets may be required by the custom widget javascript. The base -// url for the notebook is not known at build time and is therefore computed -// dynamically. -__webpack_public_path__ = document.querySelector('body').getAttribute('data-base-url') + 'nbextensions/{{ cookiecutter.npm_package_name }}'; - // Configure requirejs if (window.require) { diff --git a/{{cookiecutter.github_project_name}}/js/webpack.config.js b/{{cookiecutter.github_project_name}}/js/webpack.config.js index 41c90a1..0f8a64f 100644 --- a/{{cookiecutter.github_project_name}}/js/webpack.config.js +++ b/{{cookiecutter.github_project_name}}/js/webpack.config.js @@ -24,7 +24,6 @@ module.exports = (env, argv) => { filename: 'extension.js', path: path.resolve(__dirname, '..', '{{ cookiecutter.python_package_name }}', 'nbextension'), libraryTarget: 'amd', - publicPath: '' // publicPath is set in extension.js }, devtool }, @@ -39,7 +38,6 @@ module.exports = (env, argv) => { filename: 'index.js', path: path.resolve(__dirname, '..', '{{ cookiecutter.python_package_name }}', 'nbextension'), libraryTarget: 'amd', - publicPath: '', }, devtool, module: { @@ -49,24 +47,19 @@ module.exports = (env, argv) => { }, {// Embeddable {{ cookiecutter.npm_package_name }} bundle // - // This bundle is generally almost identical to the notebook bundle - // containing the custom widget views and models. + // This bundle is identical to the notebook bundle containing the custom + // widget views and models. The only difference is it is placed in the + // dist/ directory and shipped with the npm package for use from a CDN + // like jsdelivr. // - // The only difference is in the configuration of the webpack public path - // for the static assets. + // The target bundle is always `dist/index.js`, which is the path + // required by the custom widget embedder. // - // It will be automatically distributed by unpkg to work with the static - // widget embedder. - // - // The target bundle is always `dist/index.js`, which is the path required - // by the custom widget embedder. - // - entry: './lib/embed.js', + entry: './lib/index.js', output: { filename: 'index.js', path: path.resolve(__dirname, 'dist'), libraryTarget: 'amd', - publicPath: 'https://unpkg.com/{{ cookiecutter.npm_package_name }}@' + version + '/dist/' }, devtool, module: { From 9797c3feb0a9b7ad368f51f92358738250982655 Mon Sep 17 00:00:00 2001 From: Jason Grout Date: Thu, 2 Jun 2022 04:57:18 -0600 Subject: [PATCH 2/3] Set publicPath automatically for AMD modules It seems that the auto public path logic in webpack does not work for AMD modules, since document.currentScript only works when the script is initially executed, not in a callback. In the cases where we know we are compiling to an AMD module, we can use the requirejs magic 'module' dependency to get the url of the file, and from that do our own auto public path magic. We encapsulate this auto public path setting into its own file so that it does not intrude on user code, and is only used when we know in the webpack config that we are compiling to an AMD module. --- .../js/amd-public-path.js | 8 ++++++++ .../js/webpack.config.js | 12 ++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 {{cookiecutter.github_project_name}}/js/amd-public-path.js diff --git a/{{cookiecutter.github_project_name}}/js/amd-public-path.js b/{{cookiecutter.github_project_name}}/js/amd-public-path.js new file mode 100644 index 0000000..4d51b3b --- /dev/null +++ b/{{cookiecutter.github_project_name}}/js/amd-public-path.js @@ -0,0 +1,8 @@ +// In an AMD module, we set the public path using the magic requirejs 'module' dependency +// See https://github.com/requirejs/requirejs/wiki/Differences-between-the-simplified-CommonJS-wrapper-and-standard-AMD-define#module +// Since 'module' is a requirejs magic module, we must include 'module' in the webpack externals configuration. +var module = require('module'); +var url = new URL(module.uri, document.location) +// Using lastIndexOf('/')+1 gives us the empty string if there is no '/', so pathname becomes '/' +url.pathname = url.pathname.slice(0,url.pathname.lastIndexOf('/')+1); +__webpack_public_path__ = `${url.origin}${url.pathname}`; diff --git a/{{cookiecutter.github_project_name}}/js/webpack.config.js b/{{cookiecutter.github_project_name}}/js/webpack.config.js index 0f8a64f..a8f6ee6 100644 --- a/{{cookiecutter.github_project_name}}/js/webpack.config.js +++ b/{{cookiecutter.github_project_name}}/js/webpack.config.js @@ -33,17 +33,19 @@ module.exports = (env, argv) => { // custom widget. // It must be an amd module // - entry: './lib/index.js', + entry: ['./amd-public-path.js', './lib/index.js'], output: { filename: 'index.js', path: path.resolve(__dirname, '..', '{{ cookiecutter.python_package_name }}', 'nbextension'), libraryTarget: 'amd', + publicPath: '', // Set in amd-public-path.js }, devtool, module: { rules: rules }, - externals: ['@jupyter-widgets/base'] + // 'module' is the magic requirejs dependency used to set the publicPath + externals: ['@jupyter-widgets/base', 'module'] }, {// Embeddable {{ cookiecutter.npm_package_name }} bundle // @@ -55,17 +57,19 @@ module.exports = (env, argv) => { // The target bundle is always `dist/index.js`, which is the path // required by the custom widget embedder. // - entry: './lib/index.js', + entry: ['./amd-public-path.js', './lib/index.js'], output: { filename: 'index.js', path: path.resolve(__dirname, 'dist'), libraryTarget: 'amd', + publicPath: '', // Set in amd-public-path.js }, devtool, module: { rules: rules }, - externals: ['@jupyter-widgets/base'] + // 'module' is the magic requirejs dependency used to set the publicPath + externals: ['@jupyter-widgets/base', 'module'] } ]; } From 179707b2d34787bb1f2c51184b7cff4f7731f721 Mon Sep 17 00:00:00 2001 From: Jason Grout Date: Sat, 6 Aug 2022 15:09:43 -0600 Subject: [PATCH 3/3] Lint --- {{cookiecutter.github_project_name}}/js/webpack.config.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/{{cookiecutter.github_project_name}}/js/webpack.config.js b/{{cookiecutter.github_project_name}}/js/webpack.config.js index a8f6ee6..3201b7f 100644 --- a/{{cookiecutter.github_project_name}}/js/webpack.config.js +++ b/{{cookiecutter.github_project_name}}/js/webpack.config.js @@ -18,7 +18,6 @@ module.exports = (env, argv) => { // some configuration for requirejs, and provides the legacy // "load_ipython_extension" function which is required for any notebook // extension. - // entry: './lib/extension.js', output: { filename: 'extension.js', @@ -32,7 +31,6 @@ module.exports = (env, argv) => { // This bundle contains the implementation for the custom widget views and // custom widget. // It must be an amd module - // entry: ['./amd-public-path.js', './lib/index.js'], output: { filename: 'index.js', @@ -56,7 +54,6 @@ module.exports = (env, argv) => { // // The target bundle is always `dist/index.js`, which is the path // required by the custom widget embedder. - // entry: ['./amd-public-path.js', './lib/index.js'], output: { filename: 'index.js',