mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-10-11 14:06:20 +08:00
Dynamically import Vega-Lite JS when needed (#673)
This commit is contained in:
parent
959e799d6e
commit
e38d075fc2
3 changed files with 45 additions and 17 deletions
|
@ -1,8 +1,16 @@
|
||||||
import * as vega from "vega";
|
|
||||||
import vegaEmbed from "vega-embed";
|
|
||||||
import { getAttributeOrThrow } from "../lib/attribute";
|
import { getAttributeOrThrow } from "../lib/attribute";
|
||||||
import { throttle } from "../lib/utils";
|
import { throttle } from "../lib/utils";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dynamically imports the vega-related modules.
|
||||||
|
*/
|
||||||
|
function importVega() {
|
||||||
|
return import(
|
||||||
|
/* webpackChunkName: "vega" */
|
||||||
|
"./vega"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// See https://github.com/vega/vega-lite/blob/b61b13c2cbd4ecde0448544aff6cdaea721fd22a/src/compile/data/assemble.ts#L228-L231
|
// See https://github.com/vega/vega-lite/blob/b61b13c2cbd4ecde0448544aff6cdaea721fd22a/src/compile/data/assemble.ts#L228-L231
|
||||||
const DEFAULT_DATASET_NAME = "source_0";
|
const DEFAULT_DATASET_NAME = "source_0";
|
||||||
|
|
||||||
|
@ -37,7 +45,10 @@ const VegaLite = {
|
||||||
spec.data = { values: [] };
|
spec.data = { values: [] };
|
||||||
}
|
}
|
||||||
|
|
||||||
this.state.viewPromise = vegaEmbed(this.state.container, spec, {})
|
this.state.viewPromise = importVega()
|
||||||
|
.then(({ vegaEmbed }) => {
|
||||||
|
return vegaEmbed(this.state.container, spec, {});
|
||||||
|
})
|
||||||
.then((result) => result.view)
|
.then((result) => result.view)
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
const message = `Failed to render the given Vega-Lite specification, got the following error:\n\n ${error.message}\n\nMake sure to check for typos.`;
|
const message = `Failed to render the given Vega-Lite specification, got the following error:\n\n ${error.message}\n\nMake sure to check for typos.`;
|
||||||
|
@ -57,10 +68,11 @@ const VegaLite = {
|
||||||
|
|
||||||
this.state.viewPromise.then((view) => {
|
this.state.viewPromise.then((view) => {
|
||||||
const currentData = view.data(dataset);
|
const currentData = view.data(dataset);
|
||||||
const changeset = buildChangeset(currentData, data, window);
|
buildChangeset(currentData, data, window).then((changeset) => {
|
||||||
// Schedule resize after the run finishes
|
// Schedule resize after the run finishes
|
||||||
throttledResize(view);
|
throttledResize(view);
|
||||||
view.change(dataset, changeset).run();
|
view.change(dataset, changeset).run();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -84,17 +96,19 @@ function getProps(hook) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildChangeset(currentData, newData, window) {
|
function buildChangeset(currentData, newData, window) {
|
||||||
if (window === 0) {
|
return importVega().then(({ vega }) => {
|
||||||
return vega.changeset().remove(currentData);
|
if (window === 0) {
|
||||||
} else if (window) {
|
return vega.changeset().remove(currentData);
|
||||||
const toInsert = newData.slice(-window);
|
} else if (window) {
|
||||||
const freeSpace = Math.max(window - toInsert.length, 0);
|
const toInsert = newData.slice(-window);
|
||||||
const toRemove = currentData.slice(0, -freeSpace);
|
const freeSpace = Math.max(window - toInsert.length, 0);
|
||||||
|
const toRemove = currentData.slice(0, -freeSpace);
|
||||||
|
|
||||||
return vega.changeset().remove(toRemove).insert(toInsert);
|
return vega.changeset().remove(toRemove).insert(toInsert);
|
||||||
} else {
|
} else {
|
||||||
return vega.changeset().insert(newData);
|
return vega.changeset().insert(newData);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export default VegaLite;
|
export default VegaLite;
|
||||||
|
|
4
assets/js/vega_lite/vega.js
Normal file
4
assets/js/vega_lite/vega.js
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
import * as vega from "vega";
|
||||||
|
import vegaEmbed from "vega-embed";
|
||||||
|
|
||||||
|
export { vega, vegaEmbed };
|
|
@ -56,6 +56,16 @@ module.exports = (env, options) => {
|
||||||
],
|
],
|
||||||
optimization: {
|
optimization: {
|
||||||
minimizer: ["...", new CssMinimizerPlugin()],
|
minimizer: ["...", new CssMinimizerPlugin()],
|
||||||
|
splitChunks: {
|
||||||
|
cacheGroups: {
|
||||||
|
// Chunk splitting is by default enabled for all async chunks,
|
||||||
|
// so for the dynamically loaded js/vega_lite/vega.js Webpack
|
||||||
|
// would produce one almost empty chunk and then a vendor chunk
|
||||||
|
// with "vega" and "vega-embed". We want to dynamically load all
|
||||||
|
// of it at once, so we disable the default vendors chunk
|
||||||
|
defaultVendors: false
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
fallback: {
|
fallback: {
|
||||||
|
|
Loading…
Add table
Reference in a new issue