mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-01-26 16:58:50 +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 { 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
|
||||
const DEFAULT_DATASET_NAME = "source_0";
|
||||
|
||||
|
@ -37,7 +45,10 @@ const VegaLite = {
|
|||
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)
|
||||
.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.`;
|
||||
|
@ -57,10 +68,11 @@ const VegaLite = {
|
|||
|
||||
this.state.viewPromise.then((view) => {
|
||||
const currentData = view.data(dataset);
|
||||
const changeset = buildChangeset(currentData, data, window);
|
||||
// Schedule resize after the run finishes
|
||||
throttledResize(view);
|
||||
view.change(dataset, changeset).run();
|
||||
buildChangeset(currentData, data, window).then((changeset) => {
|
||||
// Schedule resize after the run finishes
|
||||
throttledResize(view);
|
||||
view.change(dataset, changeset).run();
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
@ -84,17 +96,19 @@ function getProps(hook) {
|
|||
}
|
||||
|
||||
function buildChangeset(currentData, newData, window) {
|
||||
if (window === 0) {
|
||||
return vega.changeset().remove(currentData);
|
||||
} else if (window) {
|
||||
const toInsert = newData.slice(-window);
|
||||
const freeSpace = Math.max(window - toInsert.length, 0);
|
||||
const toRemove = currentData.slice(0, -freeSpace);
|
||||
return importVega().then(({ vega }) => {
|
||||
if (window === 0) {
|
||||
return vega.changeset().remove(currentData);
|
||||
} else if (window) {
|
||||
const toInsert = newData.slice(-window);
|
||||
const freeSpace = Math.max(window - toInsert.length, 0);
|
||||
const toRemove = currentData.slice(0, -freeSpace);
|
||||
|
||||
return vega.changeset().remove(toRemove).insert(toInsert);
|
||||
} else {
|
||||
return vega.changeset().insert(newData);
|
||||
}
|
||||
return vega.changeset().remove(toRemove).insert(toInsert);
|
||||
} else {
|
||||
return vega.changeset().insert(newData);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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: {
|
||||
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: {
|
||||
fallback: {
|
||||
|
|
Loading…
Reference in a new issue