2023-04-30 12:27:09 +00:00
|
|
|
---
|
|
|
|
title: SvelteKit
|
|
|
|
pagination_prev: demos/net/index
|
|
|
|
pagination_next: demos/mobile/index
|
|
|
|
---
|
|
|
|
|
|
|
|
import current from '/version.js';
|
2023-05-07 13:58:36 +00:00
|
|
|
import CodeBlock from '@theme/CodeBlock';
|
2023-04-30 12:27:09 +00:00
|
|
|
|
|
|
|
:::note
|
|
|
|
|
|
|
|
This demo covers SvelteKit. The [Svelte demo](/docs/demos/frontend/svelte)
|
|
|
|
covers general client-side strategies.
|
|
|
|
|
|
|
|
This demo uses ["Base64 Loader"](/docs/demos/static/vitejs#base64-loader)
|
|
|
|
from the ViteJS demo.
|
|
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
SvelteKit projects use ViteJS under the hood. They expose the `vite.config.js`
|
|
|
|
script. The [ViteJS demo](/docs/demos/static/vitejs) examples work as expected!
|
|
|
|
|
|
|
|
The following diagram depicts the workbook waltz:
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
flowchart LR
|
|
|
|
file[(workbook\nfile)]
|
|
|
|
subgraph SheetJS operations
|
|
|
|
base64(base64\nstring)
|
|
|
|
aoa(array of\nobjects)
|
|
|
|
end
|
|
|
|
html{{HTML\nTABLE}}
|
|
|
|
file --> |vite.config.js\ndata loader| base64
|
|
|
|
base64 --> |+page.server.js\nload function| aoa
|
|
|
|
aoa --> |+page.svelte\ncomponent| html
|
|
|
|
```
|
|
|
|
|
|
|
|
## Integration
|
|
|
|
|
|
|
|
`+page.server.js` scripts can be pre-rendered by exporting `prerender` from the
|
|
|
|
script. If the SheetJS operations are performed in the server script, only the
|
|
|
|
results will be added to the generated pages!
|
|
|
|
|
|
|
|
For static site generation, `@sveltejs/adapter-static` must be used.
|
|
|
|
|
|
|
|
### Loader
|
|
|
|
|
|
|
|
:::note
|
|
|
|
|
|
|
|
The ViteJS demo used the query `?b64` to identify files. To play nice with
|
|
|
|
SvelteKit, this demo matches the file extensions directly.
|
|
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
The loader should be added to `vite.config.js`. The code is nearly identical to
|
|
|
|
the ["Base64 Loader" ViteJS example.](/docs/demos/static/vitejs#base64-loader)
|
|
|
|
|
|
|
|
```js title="vite.config.js"
|
|
|
|
import { sveltekit } from '@sveltejs/kit/vite';
|
|
|
|
import { defineConfig } from 'vite';
|
|
|
|
import { readFileSync } from 'fs';
|
|
|
|
|
|
|
|
export default defineConfig({
|
|
|
|
assetsInclude: ['**/*.numbers', '**/*.xlsx'],
|
|
|
|
plugins: [sveltekit(), {
|
|
|
|
name: "sheet-base64",
|
|
|
|
transform(code, id) {
|
|
|
|
if(!id.match(/\.(numbers|xlsx)$/)) return;
|
|
|
|
var data = readFileSync(id, "base64");
|
|
|
|
return `export default '${data}'`;
|
|
|
|
}
|
|
|
|
}]
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
#### Types
|
|
|
|
|
|
|
|
For VSCodium integration, types can be specified in `src/app.d.ts`.
|
|
|
|
|
|
|
|
The example data loader returns Base64 strings. Declarations should be added for
|
|
|
|
each file extension supported in the loader:
|
|
|
|
|
|
|
|
```ts title="src/app.d.ts"
|
|
|
|
declare global {
|
|
|
|
declare module '*.numbers' {
|
|
|
|
const data: string;
|
|
|
|
export default data;
|
|
|
|
}
|
|
|
|
declare module '*.xlsx' {
|
|
|
|
const data: string;
|
|
|
|
export default data;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### Data Processing
|
|
|
|
|
|
|
|
For static sites, SheetJS operations should be run in `+page.server.js` .
|
|
|
|
|
|
|
|
Assuming `pres.xlsx` is stored in the `data` directory from the project root,
|
|
|
|
the relative import
|
|
|
|
|
|
|
|
```js
|
|
|
|
import b64 from "../../data/pres.xlsx"
|
|
|
|
```
|
|
|
|
|
|
|
|
will return a Base64 string which can be parsed in the script. The workbook
|
|
|
|
object can be post-processed using utility functions. The following example
|
|
|
|
uses `sheet_to_json` to generate arrays of row objects for each worksheet. The
|
|
|
|
data presented to the page will be an object whose keys are worksheet names:
|
|
|
|
|
|
|
|
```js title="src/routes/+page.server.js"
|
|
|
|
import b64 from "../../data/pres.xlsx";
|
|
|
|
import { read, utils } from "xlsx";
|
|
|
|
|
|
|
|
export const prerender = true;
|
|
|
|
|
|
|
|
/** @type {import('./$types').PageServerLoad} */
|
|
|
|
export async function load({ params }) {
|
|
|
|
const wb = read(b64);
|
|
|
|
/** @type {[string, any[]][]} */
|
|
|
|
const data = wb.SheetNames.map(n => [n, utils.sheet_to_json(wb.Sheets[n])]);
|
|
|
|
return Object.fromEntries(data);
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### Data Rendering
|
|
|
|
|
|
|
|
The shape of the data is determined by the loader. The example loader returns an
|
|
|
|
object whose keys are worksheet names and whose values are arrays of objects.
|
|
|
|
|
|
|
|
Using standard Svelte patterns, HTML tables can be generated from the data:
|
|
|
|
|
|
|
|
```html title="src/routes/+page.svelte"
|
|
|
|
<script>
|
|
|
|
/** @type {import('./$types').PageData} */
|
|
|
|
export let data;
|
|
|
|
|
|
|
|
/* `pres` will be the data from Sheet1 */
|
|
|
|
/** @type {Array<{Name: string, Index: number}>}*/
|
|
|
|
export let pres = data["Sheet1"];
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<h1>Presidents</h1>
|
|
|
|
<table><thead><th>Name</th><th>Index</th></thead><tbody>
|
|
|
|
{#each pres as p}<tr>
|
|
|
|
<td>{p.Name}</td>
|
|
|
|
<td>{p.Index}</td>
|
|
|
|
</tr>{/each}
|
|
|
|
</tbody></table>
|
|
|
|
```
|
|
|
|
|
|
|
|
When built using `npm run build`, SvelteKit will perform the conversion and emit
|
|
|
|
a simple HTML table without any reference to the existing spreadsheet file!
|
|
|
|
|
|
|
|
## Complete Example
|
|
|
|
|
|
|
|
:::note
|
|
|
|
|
|
|
|
This demo was tested on 2023 April 30 using SvelteKit `1.15.9`
|
|
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
### Initial Setup
|
|
|
|
|
|
|
|
1) Create a new site:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
npm create svelte@latest sheetjs-svelte
|
|
|
|
cd sheetjs-svelte
|
|
|
|
npm i
|
|
|
|
```
|
|
|
|
|
2023-05-01 01:27:02 +00:00
|
|
|
When prompted:
|
|
|
|
|
|
|
|
- `Which Svelte app template?` select `Skeleton Project`
|
|
|
|
- `Add type checking with TypeScript?` select `Yes, using JavaScript with JSDoc`
|
|
|
|
- `Select additional options` press Enter (do not select options)
|
|
|
|
|
2023-04-30 12:27:09 +00:00
|
|
|
2) Fetch the example file [`pres.xlsx`](https://sheetjs.com/pres.xlsx) and move
|
|
|
|
to a `data` subdirectory in the root of the project:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
mkdir -p data
|
|
|
|
curl -Lo data/pres.xlsx https://sheetjs.com/pres.xlsx
|
|
|
|
```
|
|
|
|
|
|
|
|
3) Install the SheetJS library:
|
|
|
|
|
2023-05-07 13:58:36 +00:00
|
|
|
<CodeBlock language="bash">{`\
|
2023-04-30 12:27:09 +00:00
|
|
|
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
|
2023-05-07 13:58:36 +00:00
|
|
|
</CodeBlock>
|
2023-04-30 12:27:09 +00:00
|
|
|
|
|
|
|
4) Replace the contents of `vite.config.js` with the contents of the code block
|
|
|
|
named [`vite.config.js` in the "Loader" section](#loader)
|
|
|
|
|
|
|
|
5) Append the lines from [`src/app.d.ts` snippet in the "Types" section](#types)
|
|
|
|
to the `src/app.d.ts` file.
|
|
|
|
|
|
|
|
6) Replace the contents of `src/routes/+page.server.ts` with the contents of the
|
|
|
|
code block named [`src/routes/+page.server.ts` in "Data Processing"](#data-processing)
|
|
|
|
|
|
|
|
7) Replace the contents of `src/routes/+page.svelte` with the contents of the
|
|
|
|
code block named [`src/routes/+page.svelte` in "Data Rendering"](#data-rendering)
|
|
|
|
|
|
|
|
### Live Reload
|
|
|
|
|
|
|
|
8) Open `data/pres.xlsx` in a spreadsheet editor like Apple Numbers or Excel.
|
|
|
|
|
|
|
|
9) Start the development server:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
npm run dev
|
|
|
|
```
|
|
|
|
|
|
|
|
Open the displayed URL (typically `http://localhost:5173`) in a web browser and
|
|
|
|
observe that the data from the spreadsheet is displayed in the page.
|
|
|
|
|
|
|
|
10) In the spreadsheet, set cell A7 to `SheetJS Dev` and cell B7 to `47`. Save
|
|
|
|
the file. After saving, the browser should automatically refresh with new data.
|
|
|
|
|
|
|
|
### Static Site
|
|
|
|
|
|
|
|
11) Stop the development server and install the static adapter:
|
|
|
|
|
|
|
|
```bash
|
2023-05-07 13:58:36 +00:00
|
|
|
npm i --save @sveltejs/adapter-static
|
2023-04-30 12:27:09 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
12) Edit `svelte.config.js` to use the new adapter:
|
|
|
|
|
|
|
|
```diff title="svelte.config.js"
|
|
|
|
-import adapter from '@sveltejs/adapter-auto';
|
|
|
|
+import adapter from '@sveltejs/adapter-static';
|
|
|
|
```
|
|
|
|
|
|
|
|
13) Build the static site:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
npm run build
|
|
|
|
```
|
|
|
|
|
|
|
|
14) Open a web browser and access the displayed URL (`http://localhost:8080`).
|
|
|
|
View the page source and confirm that the raw HTML table includes the data.
|