284 lines
7.0 KiB
Markdown
284 lines
7.0 KiB
Markdown
|
---
|
||
|
title: ViteJS
|
||
|
pagination_prev: demos/extensions/index
|
||
|
pagination_next: demos/gsheet
|
||
|
sidebar_custom_props:
|
||
|
type: bundler
|
||
|
---
|
||
|
|
||
|
:::note
|
||
|
|
||
|
This demo covers static asset imports. For processing files in the browser, the
|
||
|
["Bundlers" demo](/docs/demos/bundler#vite) includes an example.
|
||
|
|
||
|
:::
|
||
|
|
||
|
## Loaders
|
||
|
|
||
|
ViteJS supports static asset imports, but the default raw loader interprets data
|
||
|
as UTF-8 strings. This corrupts binary formats like XLSX and XLS, but a custom
|
||
|
loader can override the default behavior.
|
||
|
|
||
|
:::note Recommendation
|
||
|
|
||
|
For simple tables of data, ["Pure Data Loader"](#pure-data-loader) is strongly
|
||
|
recommended. The heavy work is performed at build time and the generated site
|
||
|
only includes the raw data.
|
||
|
|
||
|
For more complex parsing or display logic, ["Base64 Loader"](#base64-loader) is
|
||
|
preferable. Since the raw parsing logic is performed in the page,
|
||
|
|
||
|
:::
|
||
|
|
||
|
### Pure Data Loader
|
||
|
|
||
|
For a pure static site, a plugin can load data into an array of row objects. The
|
||
|
SheetJS work is performed in the plugin. The library is not loaded in the page!
|
||
|
|
||
|
```js title="vite.config.js"
|
||
|
import { readFileSync } from 'fs';
|
||
|
import { read, utils } from 'xlsx';
|
||
|
import { defineConfig } from 'vite';
|
||
|
|
||
|
export default defineConfig({
|
||
|
assetsInclude: ['**/*.xlsx'], // xlsx file should be treated as assets
|
||
|
|
||
|
plugins: [
|
||
|
{ // this plugin handles ?sheetjs tags
|
||
|
name: "vite-sheet",
|
||
|
transform(code, id) {
|
||
|
if(!id.match(/\?sheetjs$/)) return;
|
||
|
var wb = read(readFileSync(id.replace(/\?sheetjs$/, "")));
|
||
|
var data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
|
||
|
return `export default JSON.parse('${JSON.stringify(data)}')`;
|
||
|
}
|
||
|
}
|
||
|
]
|
||
|
});
|
||
|
```
|
||
|
|
||
|
This loader uses the query `sheetjs`:
|
||
|
|
||
|
```js title="main.js"
|
||
|
import data from './data.xlsx?sheetjs';
|
||
|
|
||
|
document.querySelector('#app').innerHTML = `<div><pre>
|
||
|
${data.map(row => JSON.stringify(row)).join("\n")}
|
||
|
</pre></div>`;
|
||
|
```
|
||
|
|
||
|
### Base64 Loader
|
||
|
|
||
|
This loader pulls in data as a Base64 string that can be read with `XLSX.read`.
|
||
|
While this approach works, it is not recommended since it loads the library in
|
||
|
the front-end site.
|
||
|
|
||
|
```js title="vite.config.js"
|
||
|
import { readFileSync } from 'fs';
|
||
|
import { defineConfig } from 'vite';
|
||
|
|
||
|
export default defineConfig({
|
||
|
assetsInclude: ['**/*.xlsx'], // mark that xlsx file should be treated as assets
|
||
|
|
||
|
plugins: [
|
||
|
{ // this plugin handles ?b64 tags
|
||
|
name: "vite-b64-plugin",
|
||
|
transform(code, id) {
|
||
|
if(!id.match(/\?b64$/)) return;
|
||
|
var path = id.replace(/\?b64/, "");
|
||
|
var data = readFileSync(path, "base64");
|
||
|
return `export default '${data}'`;
|
||
|
}
|
||
|
}
|
||
|
]
|
||
|
});
|
||
|
```
|
||
|
|
||
|
When importing using the `b64` query, the raw Base64 string will be exposed.
|
||
|
This can be read directly with `XLSX.read` in JS code:
|
||
|
|
||
|
```js title="main.js"
|
||
|
import { read, utils } from "xlsx";
|
||
|
|
||
|
/* reference workbook */
|
||
|
import b64 from './data.xlsx?b64';
|
||
|
/* parse workbook and export first sheet to CSV */
|
||
|
const wb = read(b64);
|
||
|
const wsname = wb.SheetNames[0];
|
||
|
const csv = utils.sheet_to_csv(wb.Sheets[wsname]);
|
||
|
|
||
|
document.querySelector('#app').innerHTML = `<div><pre>
|
||
|
<b>${wsname}</b>
|
||
|
${csv}
|
||
|
</pre></div>`;
|
||
|
```
|
||
|
|
||
|
## Complete Demo
|
||
|
|
||
|
:::note
|
||
|
|
||
|
This demo was tested on 2023 January 14 against `vite v4.0.4`.
|
||
|
|
||
|
:::
|
||
|
|
||
|
### Initial Setup
|
||
|
|
||
|
1) Create a new site using the `vue-ts` template:
|
||
|
|
||
|
```bash
|
||
|
npm create vite@latest sheetjs-vite -- --template vue-ts
|
||
|
cd sheetjs-vite
|
||
|
npm install
|
||
|
npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz
|
||
|
```
|
||
|
|
||
|
2) Replace `vite.config.ts` with the following:
|
||
|
|
||
|
```js title="vite.config.ts"
|
||
|
import { defineConfig } from 'vite'
|
||
|
import vue from '@vitejs/plugin-vue'
|
||
|
import { readFileSync } from 'fs';
|
||
|
import { read, utils } from 'xlsx';
|
||
|
|
||
|
export default defineConfig({
|
||
|
assetsInclude: ['**/*.xlsx'], // xlsx file should be treated as assets
|
||
|
|
||
|
plugins: [
|
||
|
vue(),
|
||
|
{ // this plugin handles ?sheetjs tags
|
||
|
name: "vite-sheet",
|
||
|
transform(code, id) {
|
||
|
if(!id.match(/\?sheetjs$/)) return;
|
||
|
var wb = read(readFileSync(id.replace(/\?sheetjs$/, "")));
|
||
|
var data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
|
||
|
return `export default JSON.parse('${JSON.stringify(data)}')`;
|
||
|
}
|
||
|
},
|
||
|
{ // this plugin handles ?b64 tags
|
||
|
name: "vite-b64-plugin",
|
||
|
transform(code, id) {
|
||
|
if(!id.match(/\?b64$/)) return;
|
||
|
var path = id.replace(/\?b64/, "");
|
||
|
var data = readFileSync(path, "base64");
|
||
|
return `export default '${data}'`;
|
||
|
}
|
||
|
}
|
||
|
]
|
||
|
});
|
||
|
```
|
||
|
|
||
|
3) Make a `data` folder and download <https://sheetjs.com/pres.xlsx> :
|
||
|
|
||
|
```bash
|
||
|
mkdir -p data
|
||
|
curl -L -o data/pres.xlsx https://sheetjs.com/pres.xlsx
|
||
|
```
|
||
|
|
||
|
### Pure Data Test
|
||
|
|
||
|
4) Run the dev server:
|
||
|
|
||
|
```bash
|
||
|
npm run dev
|
||
|
```
|
||
|
|
||
|
Open a browser window to the displayed URL (typically http://localhost:5173 )
|
||
|
|
||
|
5) Replace the component `src/components/HelloWorld.vue` with:
|
||
|
|
||
|
```html title="src/components/HelloWorld.vue"
|
||
|
<script setup lang="ts">
|
||
|
// @ts-ignore
|
||
|
import data from '../../data/pres.xlsx?sheetjs';
|
||
|
</script>
|
||
|
|
||
|
<template>
|
||
|
<table>
|
||
|
<tr><th>Name</th><th>Index</th></tr>
|
||
|
<tr v-for="(row,R) in data" v-bind:key="R">
|
||
|
<td>{{row.Name}}</td>
|
||
|
<td>{{row.Index}}</td>
|
||
|
</tr>
|
||
|
</table>
|
||
|
</template>
|
||
|
```
|
||
|
|
||
|
Save and refresh the page. A data table should be displayed
|
||
|
|
||
|
6) Stop the dev server and build the site
|
||
|
|
||
|
```bash
|
||
|
npm run build
|
||
|
npx http-server dist/
|
||
|
```
|
||
|
|
||
|
The terminal will display a url like http://127.0.0.1:8080. Access that page
|
||
|
with a web browser.
|
||
|
|
||
|
7) To confirm that only the raw data is present in the page, view the page
|
||
|
source. The code will reference some script like `/assets/index-HASH.js`.
|
||
|
Open that script. Searching for `Bill Clinton` reveals the following:
|
||
|
|
||
|
```
|
||
|
JSON.parse('[{"Name":"Bill Clinton","Index":42}
|
||
|
```
|
||
|
|
||
|
Searching for `BESSELJ` should reveal no results. The SheetJS scripts are not
|
||
|
included in the final site!
|
||
|
|
||
|
### Base64 Test
|
||
|
|
||
|
8) Run the dev server:
|
||
|
|
||
|
```bash
|
||
|
npm run dev
|
||
|
```
|
||
|
|
||
|
Open a browser window to the displayed URL.
|
||
|
|
||
|
9) Replace the component `src/components/HelloWorld.vue` with:
|
||
|
|
||
|
```html title="src/components/HelloWorld.vue"
|
||
|
<script setup lang="ts">
|
||
|
// @ts-ignore
|
||
|
import b64 from '../../data/pres.xlsx?b64';
|
||
|
import { read, utils } from "xlsx";
|
||
|
/* parse workbook and convert first sheet to row array */
|
||
|
const wb = read(b64);
|
||
|
const ws = wb.Sheets[wb.SheetNames[0]];
|
||
|
interface IPresident { Name: string; Index: number; };
|
||
|
const data = utils.sheet_to_json<IPresident>(ws);
|
||
|
</script>
|
||
|
|
||
|
<template>
|
||
|
<table>
|
||
|
<tr><th>Name</th><th>Index</th></tr>
|
||
|
<tr v-for="(row,R) in data" v-bind:key="R">
|
||
|
<td>{{row.Name}}</td>
|
||
|
<td>{{row.Index}}</td>
|
||
|
</tr>
|
||
|
</table>
|
||
|
</template>
|
||
|
```
|
||
|
|
||
|
10) Stop the dev server and build the site
|
||
|
|
||
|
```bash
|
||
|
npm run build
|
||
|
npx http-server dist/
|
||
|
```
|
||
|
|
||
|
The terminal will display a url like http://127.0.0.1:8080. Access that page
|
||
|
with a web browser.
|
||
|
|
||
|
11) To confirm that only the raw data is present in the page, view the page
|
||
|
source. The code will reference some script like `/assets/index-HASH.js`.
|
||
|
Open that script. Searching for `Bill Clinton` should yield no results.
|
||
|
Searching for `BESSELJ` should match the code:
|
||
|
|
||
|
```
|
||
|
425:"BESSELJ"
|
||
|
```
|
||
|
|
||
|
The SheetJS library is embedded in the final site.
|