Skip to content

Commit 110e728

Browse files
gjmooneyjtpio
andauthored
Add webpack prod config (#7513)
* Add webpack config for prod * add optimization * rename top package * Add HtmlWebpackPlugin - rough draft * Move templates and ignore generated html * Use loop to create HtmlWebpackPlugins * Remove bundle.js from ensured-targets --------- Co-authored-by: Jeremy Tuloup <[email protected]>
1 parent 5cac611 commit 110e728

18 files changed

+577
-217
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,6 @@ ui-tests/playwright-report
135135
.pnp.*
136136
ui-tests/.yarn/*
137137
ui-tests/.pnp.*
138+
139+
# generated html
140+
notebook/templates/*.html

app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"private": true,
55
"scripts": {
66
"build": "webpack",
7-
"build:prod": "webpack --mode=production",
7+
"build:prod": "webpack --config ./webpack.prod.config.js",
88
"clean": "rimraf build && jlpm run clean:static",
99
"clean:static": "rimraf -g \"../notebook/static/!(favicons)\"",
1010
"watch": "webpack --config ./webpack.config.watch.js"
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1" />
6+
<title>{{page_config['appName'] | e}} - Console</title>
7+
{% block favicon %}
8+
<link
9+
rel="icon"
10+
type="image/x-icon"
11+
href="{{ page_config['fullStaticUrl'] | e }}/favicons/favicon-console.ico"
12+
class="favicon"
13+
/>
14+
{% endblock %} {% if custom_css %}
15+
<link
16+
rel="stylesheet"
17+
type="text/css"
18+
href="{{ base_url | escape }}custom/custom.css"
19+
/>
20+
{% endif %}
21+
</head>
22+
<body class="jp-ThemedContainer">
23+
{# Copy so we do not modify the page_config with updates. #} {% set
24+
page_config_full = page_config.copy() %} {# Set a dummy variable - we just
25+
want the side effect of the update. #} {% set _ =
26+
page_config_full.update(baseUrl=base_url, wsUrl=ws_url) %} {# Sentinel value
27+
to say that we are on the tree page #} {% set _ =
28+
page_config_full.update(notebookPage='consoles') %}
29+
30+
<script id="jupyter-config-data" type="application/json">
31+
{{ page_config_full | tojson }}
32+
</script>
33+
34+
<script type="text/javascript">
35+
/* Remove token from URL. */
36+
(function () {
37+
var parsedUrl = new URL(window.location.href);
38+
if (parsedUrl.searchParams.get('token')) {
39+
parsedUrl.searchParams.delete('token');
40+
window.history.replaceState({}, '', parsedUrl.href);
41+
}
42+
})();
43+
</script>
44+
</body>
45+
</html>

app/templates/edit_template.html

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1" />
6+
<title>{{page_config['appName'] | e}} - Edit</title>
7+
{% block favicon %}
8+
<link
9+
rel="icon"
10+
type="image/x-icon"
11+
href="{{ base_url | escape }}static/favicons/favicon-file.ico"
12+
class="favicon"
13+
/>
14+
{% endblock %}
15+
</head>
16+
<body class="jp-ThemedContainer" data-notebook="edit">
17+
{# Copy so we do not modify the page_config with updates. #} {% set
18+
page_config_full = page_config.copy() %} {# Set a dummy variable - we just
19+
want the side effect of the update. #} {% set _ =
20+
page_config_full.update(baseUrl=base_url, wsUrl=ws_url) %} {# Sentinel value
21+
to say that we are on the tree page #} {% set _ =
22+
page_config_full.update(notebookPage='edit') %}
23+
24+
<script id="jupyter-config-data" type="application/json">
25+
{{ page_config_full | tojson }}
26+
</script>
27+
28+
<script type="text/javascript">
29+
/* Remove token from URL. */
30+
(function () {
31+
var parsedUrl = new URL(window.location.href);
32+
if (parsedUrl.searchParams.get('token')) {
33+
parsedUrl.searchParams.delete('token');
34+
window.history.replaceState({}, '', parsedUrl.href);
35+
}
36+
})();
37+
</script>
38+
</body>
39+
</html>
File renamed without changes.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1" />
6+
<title>{{page_config['appName'] | e}} - Notebook</title>
7+
{% block favicon %}
8+
<link
9+
rel="icon"
10+
type="image/x-icon"
11+
href="{{ base_url | escape }}static/favicons/favicon-notebook.ico"
12+
class="favicon"
13+
/>
14+
{% endblock %} {% if custom_css %}
15+
<link
16+
rel="stylesheet"
17+
type="text/css"
18+
href="{{ base_url | escape }}custom/custom.css"
19+
/>
20+
{% endif %}
21+
</head>
22+
<body class="jp-ThemedContainer" data-notebook="notebooks">
23+
{# Copy so we do not modify the page_config with updates. #} {% set
24+
page_config_full = page_config.copy() %} {# Set a dummy variable - we just
25+
want the side effect of the update. #} {% set _ =
26+
page_config_full.update(baseUrl=base_url, wsUrl=ws_url) %} {# Sentinel value
27+
to say that we are on the tree page #} {% set _ =
28+
page_config_full.update(notebookPage='notebooks') %}
29+
30+
<script id="jupyter-config-data" type="application/json">
31+
{{ page_config_full | tojson }}
32+
</script>
33+
34+
<script type="text/javascript">
35+
/* Remove token from URL. */
36+
(function () {
37+
var parsedUrl = new URL(window.location.href);
38+
if (parsedUrl.searchParams.get('token')) {
39+
parsedUrl.searchParams.delete('token');
40+
window.history.replaceState({}, '', parsedUrl.href);
41+
}
42+
})();
43+
</script>
44+
</body>
45+
</html>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1" />
6+
<title>{{page_config['appName'] | e}} - Terminal</title>
7+
{% block favicon %}
8+
<link
9+
rel="icon"
10+
type="image/x-icon"
11+
href="{{ base_url | escape }}static/favicons/favicon-terminal.ico"
12+
class="favicon"
13+
/>
14+
{% endblock %} {% if custom_css %}
15+
<link
16+
rel="stylesheet"
17+
type="text/css"
18+
href="{{ base_url | escape }}custom/custom.css"
19+
/>
20+
{% endif %}
21+
</head>
22+
<body class="jp-ThemedContainer">
23+
{# Copy so we do not modify the page_config with updates. #} {% set
24+
page_config_full = page_config.copy() %} {# Set a dummy variable - we just
25+
want the side effect of the update. #} {% set _ =
26+
page_config_full.update(baseUrl=base_url, wsUrl=ws_url) %} {# Sentinel value
27+
to say that we are on the tree page #} {% set _ =
28+
page_config_full.update(notebookPage='terminals') %}
29+
30+
<script id="jupyter-config-data" type="application/json">
31+
{{ page_config_full | tojson }}
32+
</script>
33+
34+
<script type="text/javascript">
35+
/* Remove token from URL. */
36+
(function () {
37+
var parsedUrl = new URL(window.location.href);
38+
if (parsedUrl.searchParams.get('token')) {
39+
parsedUrl.searchParams.delete('token');
40+
window.history.replaceState({}, '', parsedUrl.href);
41+
}
42+
})();
43+
</script>
44+
</body>
45+
</html>

app/templates/tree_template.html

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1" />
6+
<title>Home</title>
7+
{% block favicon %}
8+
<link
9+
rel="icon"
10+
type="image/x-icon"
11+
href="{{ base_url | escape }}static/favicons/favicon.ico"
12+
class="favicon"
13+
/>
14+
{% endblock %} {% if custom_css %}
15+
<link
16+
rel="stylesheet"
17+
type="text/css"
18+
href="{{ base_url | escape }}custom/custom.css"
19+
/>
20+
{% endif %}
21+
</head>
22+
<body class="jp-ThemedContainer">
23+
{# Copy so we do not modify the page_config with updates. #} {% set
24+
page_config_full = page_config.copy() %} {# Set a dummy variable - we just
25+
want the side effect of the update. #} {% set _ =
26+
page_config_full.update(baseUrl=base_url, wsUrl=ws_url) %} {# Sentinel value
27+
to say that we are on the tree page #} {% set _ =
28+
page_config_full.update(notebookPage='tree') %}
29+
30+
<script id="jupyter-config-data" type="application/json">
31+
{{ page_config_full | tojson }}
32+
</script>
33+
34+
<script type="text/javascript">
35+
/* Remove token from URL. */
36+
(function () {
37+
var parsedUrl = new URL(window.location.href);
38+
if (parsedUrl.searchParams.get('token')) {
39+
parsedUrl.searchParams.delete('token');
40+
window.history.replaceState({}, '', parsedUrl.href);
41+
}
42+
})();
43+
</script>
44+
</body>
45+
</html>

app/webpack.config.js

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const BundleAnalyzerPlugin =
1515

1616
const Build = require('@jupyterlab/builder').Build;
1717
const WPPlugin = require('@jupyterlab/builder').WPPlugin;
18+
const HtmlWebpackPlugin = require('html-webpack-plugin');
1819
const baseConfig = require('@jupyterlab/builder/lib/webpack.config.base');
1920

2021
const data = require('./package.json');
@@ -204,22 +205,55 @@ if (process.argv.includes('--analyze')) {
204205
extras.push(new BundleAnalyzerPlugin());
205206
}
206207

208+
const htmlPlugins = [];
209+
['consoles', 'edit', 'error', 'notebooks', 'terminals', 'tree'].forEach(
210+
(name) => {
211+
htmlPlugins.push(
212+
new HtmlWebpackPlugin({
213+
chunksSortMode: 'none',
214+
template: path.join(
215+
path.resolve('./templates'),
216+
`${name}_template.html`
217+
),
218+
title: name,
219+
filename: path.join(
220+
path.resolve(__dirname, '..', 'notebook/templates'),
221+
`${name}.html`
222+
),
223+
})
224+
);
225+
}
226+
);
227+
207228
module.exports = [
208229
merge(baseConfig, {
209230
mode: 'development',
210231
entry: ['./publicpath.js', './' + path.relative(__dirname, entryPoint)],
211232
output: {
212233
path: path.resolve(__dirname, '..', 'notebook/static/'),
234+
publicPath: '{{page_config.fullStaticUrl}}/',
213235
library: {
214236
type: 'var',
215237
name: ['_JUPYTERLAB', 'CORE_OUTPUT'],
216238
},
217-
filename: 'bundle.js',
239+
filename: '[name].[contenthash].js',
240+
},
241+
optimization: {
242+
splitChunks: {
243+
chunks: 'all',
244+
cacheGroups: {
245+
jlab_core: {
246+
test: /[\\/]node_modules[\\/]@(jupyterlab|jupyter-notebook|lumino(?!\/datagrid))[\\/]/,
247+
name: 'notebook_core',
248+
},
249+
},
250+
},
218251
},
219252
resolve: {
220253
fallback: { util: false },
221254
},
222255
plugins: [
256+
...htmlPlugins,
223257
new WPPlugin.JSONLicenseWebpackPlugin({
224258
excludedPackageTest: (packageName) =>
225259
packageName === '@jupyter-notebook/app',
@@ -235,3 +269,6 @@ module.exports = [
235269
],
236270
}),
237271
].concat(extras);
272+
273+
const logPath = path.join(buildDir, 'build_log.json');
274+
fs.writeFileSync(logPath, JSON.stringify(module.exports, null, ' '));

app/webpack.prod.config.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright (c) Jupyter Development Team.
3+
* Distributed under the terms of the Modified BSD License.
4+
*/
5+
6+
const merge = require('webpack-merge').default;
7+
const config = require('./webpack.config');
8+
const WPPlugin = require('@jupyterlab/builder').WPPlugin;
9+
10+
config[0] = merge(config[0], {
11+
mode: 'production',
12+
devtool: 'source-map',
13+
output: {
14+
// Add version argument when in production so the Jupyter server
15+
// allows caching of files (i.e., does not set the CacheControl header to no-cache to prevent caching static files)
16+
filename: '[name].[contenthash].js?v=[contenthash]',
17+
},
18+
optimization: {
19+
minimize: false,
20+
},
21+
plugins: [
22+
new WPPlugin.JSONLicenseWebpackPlugin({
23+
excludedPackageTest: (packageName) =>
24+
packageName === '@jupyter-notebook/app',
25+
}),
26+
],
27+
});
28+
29+
module.exports = config;

0 commit comments

Comments
 (0)