This is an automated email from the ASF dual-hosted git repository.
wangzx pushed a commit to branch gh-pages
in repository https://gitbox.apache.org/repos/asf/echarts-examples.git
The following commit(s) were added to refs/heads/gh-pages by this push:
new e601162f feat(explore): enable wp img acceleator CDN for zh page
e601162f is described below
commit e601162f27aeb5cffb62ab7b987a2315a56fb559
Author: plainheart <[email protected]>
AuthorDate: Mon Oct 9 01:53:38 2023 +0800
feat(explore): enable wp img acceleator CDN for zh page
---
build/copyResource.js | 70 +++++++++++++++++++---
src/common/config.js | 5 ++
src/common/helper.js | 4 ++
src/explore/ExampleCard.vue | 49 ++++++++++++++--
src/explore/Explore.vue | 137 ++++++++++++++++++++++++++------------------
5 files changed, 196 insertions(+), 69 deletions(-)
diff --git a/build/copyResource.js b/build/copyResource.js
index bfa378a4..58196a38 100644
--- a/build/copyResource.js
+++ b/build/copyResource.js
@@ -1,9 +1,11 @@
-const fs = require('fs');
+const fs = require('node:fs');
+const fsp = require('node:fs/promises');
const fse = require('fs-extra');
const globby = require('globby');
const chalk = require('chalk');
-const path = require('path');
-const assert = require('assert');
+const path = require('node:path');
+const assert = require('node:assert');
+const crypto = require('node:crypto');
const argv = require('yargs').argv;
const projectDir = __dirname;
@@ -69,7 +71,7 @@ function initEnv() {
}
async function copyResourcesToDest(config) {
- let basePath = path.resolve(projectDir, '../public');
+ const basePath = path.resolve(projectDir, '../public');
const filePaths = await globby(
[
'**/*',
@@ -84,11 +86,11 @@ async function copyResourcesToDest(config) {
console.log();
- for (let filePath of filePaths) {
+ for (const filePath of filePaths) {
fse.ensureDirSync(
path.resolve(config.releaseDestDir, path.dirname(filePath))
);
- let destPath = path.resolve(config.releaseDestDir, filePath);
+ const destPath = path.resolve(config.releaseDestDir, filePath);
fs.copyFileSync(path.resolve(basePath, filePath), destPath);
if (process.stdout.clearLine) {
@@ -100,11 +102,65 @@ async function copyResourcesToDest(config) {
}
}
+ console.log();
+
+ if (config.envType === 'asf') {
+ const rootDir = path.resolve(__dirname, '../public');
+ const thumbPaths = await globby(
+ ['data/thumb/*', 'data/thumb-*/*', 'data-*/thumb/*', 'data-*/thumb-*/*'],
+ {
+ cwd: rootDir
+ }
+ );
+ // calculate sha512 hash
+ const thumbHashMap = {};
+ console.log(
+ 'Calculating sha512 hash for example thumbs...',
+ thumbPaths.length
+ );
+ await Promise.all(
+ thumbPaths.map(async (thumbPath) => {
+ const data = await fsp.readFile(
+ path.resolve(rootDir, thumbPath),
+ 'binary'
+ );
+ const sha512 = crypto
+ .createHash('sha512')
+ .update(data)
+ .digest('hex')
+ .slice(0, 8);
+ thumbHashMap[thumbPath] = sha512;
+ })
+ );
+ const thumbHashMapPath = path.resolve(
+ config.releaseDestDir,
+ 'thumb-hash.json'
+ );
+ fs.writeFileSync(thumbHashMapPath, JSON.stringify(thumbHashMap), 'utf-8');
+
+ Object.entries(thumbHashMap).forEach(([thumbPath, hash]) => {
+ const extname = path.extname(thumbPath);
+ const hashFileName = thumbPath.replace(
+ new RegExp(extname + '$'),
+ '.' + hash + extname
+ );
+ const destPath = path.resolve(config.releaseDestDir, hashFileName);
+ fse.copyFileSync(path.resolve(basePath, thumbPath), destPath);
+ if (process.stdout.clearLine) {
+ process.stdout.clearLine();
+ process.stdout.cursorTo(0);
+ process.stdout.write(chalk.green(`resource copied to: ${destPath}`));
+ } else {
+ console.log(chalk.green(`resource copied to: ${destPath}`));
+ }
+ });
+ }
+
console.log('\ncopyResourcesToDest done.');
}
async function run() {
- let config = initEnv();
+ const config = initEnv();
await copyResourcesToDest(config);
console.log('All done.');
diff --git a/src/common/config.js b/src/common/config.js
index 40bf3776..ab20fe27 100644
--- a/src/common/config.js
+++ b/src/common/config.js
@@ -109,6 +109,11 @@ export { URL_PARAMS };
// https://npm.elemecdn.com/
export const CDN_ROOT = 'https://fastly.jsdelivr.net/npm/';
+// NOTE: can't clear the cache with query string and must change the file name
+export const IMG_ACCELERATOR_CDN = [0, 1, 2, 3].map(
+ (subdomain) => `https://i${subdomain}.wp.com`
+);
+
export const SCRIPT_URLS = {
echartsDir: `${CDN_ROOT}echarts@{{version}}`,
echartsNightlyDir: `${CDN_ROOT}echarts-nightly@{{version}}`,
diff --git a/src/common/helper.js b/src/common/helper.js
index 4836af2e..4309cfbb 100644
--- a/src/common/helper.js
+++ b/src/common/helper.js
@@ -126,3 +126,7 @@ export function isTrustedOpener() {
export function decodeBase64(str) {
return decodeURIComponent(escape(window.atob(str)));
}
+
+export function shouldEnableImgAcceleration() {
+ return store.locale === 'zh' && store.cdnRoot.includes('echarts.apache.org');
+}
diff --git a/src/explore/ExampleCard.vue b/src/explore/ExampleCard.vue
index e94f0b3a..57105245 100644
--- a/src/explore/ExampleCard.vue
+++ b/src/explore/ExampleCard.vue
@@ -28,7 +28,8 @@
<script>
import { store } from '../common/store';
-import { URL_PARAMS } from '../common/config';
+import { URL_PARAMS, IMG_ACCELERATOR_CDN } from '../common/config';
+import { shouldEnableImgAcceleration } from '../common/helper';
export default {
props: ['example'],
@@ -68,19 +69,57 @@ export default {
return './editor.html?' + hash.join('&');
},
- screenshotURLWithoutExt() {
+ enableImgAcceleration: shouldEnableImgAcceleration,
+
+ imgCDN() {
+ const cdnRoot = store.cdnRoot;
+ const acceleratorCDN =
+ this.enableImgAcceleration &&
+ IMG_ACCELERATOR_CDN[~~(Math.random() * IMG_ACCELERATOR_CDN.length)];
+ return acceleratorCDN
+ ? acceleratorCDN + '/' + cdnRoot.slice(cdnRoot.indexOf('//') + 2)
+ : cdnRoot;
+ },
+
+ exampleThumbBasePath() {
const example = this.example;
const themePostfix = this.exampleTheme ? '-' + this.exampleTheme : '';
const folder = example.isGL ? 'data-gl' : 'data';
- return `${store.cdnRoot}/${folder}/thumb${themePostfix}/${example.id}`;
+ return `${folder}/thumb${themePostfix}/${example.id}`;
},
screenshotURLWebP() {
- return this.screenshotURLWithoutExt + `.webp?_v_=${store.version}`;
+ return this.getExampleThumbPath(
+ this.exampleThumbBasePath,
+ 'webp',
+ this.imgCDN,
+ this.enableImgAcceleration
+ );
},
screenshotURLPNG() {
- return this.screenshotURLWithoutExt + `.png?_v_=${store.version}`;
+ return this.getExampleThumbPath(
+ this.exampleThumbBasePath,
+ 'png',
+ this.imgCDN,
+ this.enableImgAcceleration
+ );
+ }
+ },
+
+ methods: {
+ getExampleThumbPath(
+ thumbPathSegment,
+ imgExt,
+ imgCDN,
+ enableImgAcceleration
+ ) {
+ const hash =
+ enableImgAcceleration &&
+ (window.ec_thumb_hash || {})[thumbPathSegment + '.' + imgExt];
+ return `${imgCDN}/${thumbPathSegment}${
+ hash ? '.' + hash : ''
+ }.${imgExt}?_v_=${store.version}`;
}
}
};
diff --git a/src/explore/Explore.vue b/src/explore/Explore.vue
index 89098bf5..f397a521 100644
--- a/src/explore/Explore.vue
+++ b/src/explore/Explore.vue
@@ -68,6 +68,7 @@ import CHART_LIST from '../data/chart-list-data';
import CHART_LIST_GL from '../data/chart-list-data-gl';
import { EXAMPLE_CATEGORIES, BLACK_MAP } from '../common/config';
import { store } from '../common/store';
+import { shouldEnableImgAcceleration } from '../common/helper';
import ExampleCard from './ExampleCard.vue';
import LazyLoad from 'vanilla-lazyload/dist/lazyload.esm';
@@ -133,46 +134,6 @@ export default {
data() {
const exampleListByCategory = {};
- function addExamples(list, isGL) {
- let categoryOrder = 0;
- // Add by category order in each example.
- do {
- let added = false;
- for (let i = 0; i < list.length; i++) {
- const example = list[i];
- if (BLACK_MAP.hasOwnProperty(example.id)) {
- continue;
- }
- if (typeof example.category === 'string') {
- example.category = [example.category];
- }
-
- const categoryStr = (example.category || [])[categoryOrder];
- if (categoryStr) {
- added = true;
- let categoryObj = exampleListByCategory[categoryStr];
- if (!categoryObj) {
- categoryObj = {
- category: categoryStr,
- examples: []
- };
- exampleListByCategory[categoryStr] = categoryObj;
- }
- example.isGL = isGL;
-
- categoryObj.examples.push(example);
- }
- }
-
- if (!added) {
- break;
- }
- } while (++categoryOrder && categoryOrder < 4); // At most 4 category
- }
-
- addExamples(CHART_LIST, false);
- addExamples(CHART_LIST_GL, true);
-
return {
shared: store,
@@ -202,7 +163,7 @@ export default {
computed: {
exampleList() {
const list = [];
- for (let i = 0; i < EXAMPLE_CATEGORIES.length; i++) {
+ for (let i = 0, len = EXAMPLE_CATEGORIES.length; i < len; i++) {
const category = EXAMPLE_CATEGORIES[i];
const categoryObj = this.exampleListByCategory[category];
if (categoryObj && categoryObj.examples.length > 0) {
@@ -217,25 +178,87 @@ export default {
},
mounted() {
- window.addEventListener('hashchange', this.onHashChange);
-
- this._lazyload = new LazyLoad({
- // Container should be the scroll viewport.
- // container: this.$el.querySelector('#explore-container
.example-list-panel'),
- elements_selector: '.chart-area',
- load_delay: 400,
- class_loaded: LAZY_LOADED_CLASS,
- callback_error(img) {
- const fallbackSrc = img.src;
- const children = img.parentElement.children;
- for (let i = 0, len = children.length; i < len; i++) {
- const el = children[i];
- if (el !== img) {
- el.srcset = fallbackSrc;
+ const exampleListByCategory = {};
+
+ function addExamples(list, isGL) {
+ let categoryOrder = 0;
+ // Add by category order in each example.
+ do {
+ let added = false;
+ for (let i = 0; i < list.length; i++) {
+ const example = list[i];
+ if (BLACK_MAP.hasOwnProperty(example.id)) {
+ continue;
+ }
+ if (typeof example.category === 'string') {
+ example.category = [example.category];
}
+
+ const categoryStr = (example.category || [])[categoryOrder];
+ if (categoryStr) {
+ added = true;
+ let categoryObj = exampleListByCategory[categoryStr];
+ if (!categoryObj) {
+ categoryObj = {
+ category: categoryStr,
+ examples: []
+ };
+ exampleListByCategory[categoryStr] = categoryObj;
+ }
+ example.isGL = isGL;
+
+ categoryObj.examples.push(example);
+ }
+ }
+
+ if (!added) {
+ break;
}
+ } while (++categoryOrder && categoryOrder < 4); // At most 4 category
+ }
+
+ const onDone = () => {
+ addExamples(CHART_LIST, false);
+ addExamples(CHART_LIST_GL, true);
+
+ this.$set(this, 'exampleListByCategory', exampleListByCategory);
+
+ this.$nextTick(() => {
+ this._lazyload = new LazyLoad({
+ // Container should be the scroll viewport.
+ // container: this.$el.querySelector('#explore-container
.example-list-panel'),
+ elements_selector: '.chart-area',
+ load_delay: 400,
+ class_loaded: LAZY_LOADED_CLASS,
+ callback_error(img) {
+ const fallbackSrc = img.src;
+ const children = img.parentElement.children;
+ for (let i = 0, len = children.length; i < len; i++) {
+ const el = children[i];
+ if (el !== img) {
+ el.srcset = fallbackSrc;
+ }
+ }
+ }
+ });
+
+ setTimeout(() => {
+ this.onHashChange();
+ window.addEventListener('hashchange', this.onHashChange);
+ }, 0);
+ });
+ };
+
+ if (!shouldEnableImgAcceleration()) {
+ return onDone();
+ }
+
+ $.getJSON(`${store.cdnRoot}/thumb-hash.json?_v_=${store.version}`).always(
+ (data) => {
+ window.ec_thumb_hash = data;
+ onDone();
}
- });
+ );
},
methods: {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]