docs.sheetjs.com/docz/docs/03-demos/11-static/09-nuxtjs.md

251 lines
6.7 KiB
Markdown
Raw Normal View History

2023-01-15 03:36:13 +00:00
---
title: NuxtJS
pagination_prev: demos/extensions/index
pagination_next: demos/gsheet
---
### NuxtJS
`@nuxt/content` is a file-based CMS for Nuxt, enabling static-site generation
and on-demand server rendering powered by spreadsheets.
:::note
This demo was tested on 2022 November 18 against Nuxt Content `v1.15.1`.
:::
:::warning
Nuxt Content `v2` (NuxtJS `v3`) employs a different architecture from `v1`.
There are known bugs related to corrupted binary spreadsheet files.
Greenfield projects should stick to the stable NuxtJS + Nuxt Content versions
until the issues are resolved.
:::
## Configuration
Through an override in `nuxt.config.js`, Nuxt Content will use custom parsers.
Differences from a stock `create-nuxt-app` config are shown below:
```js title="nuxt.config.js"
import { readFile, utils } from 'xlsx';
// This will be called when the files change
const parseSheet = (file, { path }) => {
// `path` is a path that can be read with `XLSX.readFile`
const wb = readFile(path);
const o = wb.SheetNames.map(name => ({ name, data: utils.sheet_to_json(wb.Sheets[name])}));
return { data: o };
}
export default {
// ...
// content.extendParser allows us to hook into the parsing step
content: {
extendParser: {
// the keys are the extensions that will be matched. The "." is required
".numbers": parseSheet,
".xlsx": parseSheet,
".xls": parseSheet,
// can add other extensions like ".fods" as desired
}
},
// ...
}
```
## Template Use
When a spreadsheet is placed in the `content` folder, Nuxt will find it. The
data can be referenced in a view with `asyncData`. The name should not include
the extension, so `"sheetjs.numbers"` would be referenced as `"sheetjs"`:
```js
async asyncData ({$content}) {
return {
// $content('sheetjs') will match files with extensions in nuxt.config.js
data: await $content('sheetjs').fetch()
};
}
```
In the template, `data.data` is an array of objects. Each object has a `name`
property for the worksheet name and a `data` array of row objects. This maps
neatly with nested `v-for`:
```xml
<!-- loop over the worksheets -->
<div v-for="item in data.data" v-bind:key="item.name">
<table>
<!-- loop over the rows of each worksheet -->
<tr v-for="row in item.data" v-bind:key="row.Index">
<!-- here `row` is a row object generated from sheet_to_json -->
<td>{{ row.Name }}</td>
<td>{{ row.Index }}</td>
</tr>
</table>
</div>
```
## Nuxt Content Demo
:::note
The project was generated using `create-nuxt-app v4.0.0`. The generated project
used Nuxt `v2.15.8` and Nuxt Content `v1.15.1`.
:::
1) Create a stock app:
```bash
npx create-nuxt-app@4.0.0 SheetJSNuxt
```
When prompted, enter the following options:
- `Project name`: press Enter (use default `SheetJSNuxt`)
- `Programming language`: press Down Arrow (`TypeScript` selected) then Enter
- `Package manager`: select `Npm` and press Enter
- `UI framework`: select `None` and press Enter
- `Nuxt.js modules`: scroll to `Content`, select with Space, then press Enter
- `Linting tools`: press Enter (do not select any Linting tools)
- `Testing framework`: select `None` and press Enter
- `Rendering mode`: select `Universal (SSR / SSG)` and press Enter
- `Deployment target`: select `Static (Static/Jamstack hosting)` and press Enter
- `Development tools`: press Enter (do not select any Development tools)
- `What is your GitHub username?`: press Enter
- `Version control system`: select `None`
The project will be configured and modules will be installed.
2) Install the SheetJS library and start the server:
```bash
cd SheetJSNuxt
npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz
npm run dev
```
When the build finishes, the terminal will display a URL like:
```
Listening on: http://localhost:64688/
```
The server is listening on that URL. Open the link in a web browser.
3) Download <https://sheetjs.com/pres.xlsx> and move to the `content` folder.
```bash
curl -L -o content/pres.xlsx https://sheetjs.com/pres.xlsx
```
4) Modify `nuxt.config.js` as follows:
- Add the following to the top of the script:
```js
import { readFile, utils } from 'xlsx';
// This will be called when the files change
const parseSheet = (file, { path }) => {
// `path` is a path that can be read with `XLSX.readFile`
const wb = readFile(path);
const o = wb.SheetNames.map(name => ({ name, data: utils.sheet_to_json(wb.Sheets[name])}));
return { data: o };
}
```
- Look for the exported object. There should be a `content` property:
```js
// Content module configuration: https://go.nuxtjs.dev/config-content
content: {},
```
Replace the property with the following definition:
```js
// content.extendParser allows us to hook into the parsing step
content: {
extendParser: {
// the keys are the extensions that will be matched. The "." is required
".numbers": parseSheet,
".xlsx": parseSheet,
".xls": parseSheet,
// can add other extensions like ".fods" as desired
}
},
```
(If the property is missing, add it to the end of the exported object)
5) Replace `pages/index.vue` with the following:
```html
<!-- sheetjs (C) 2013-present SheetJS -- https://sheetjs.com -->
<template><div>
<div v-for="item in data.data" v-bind:key="item.name">
<h2>{{ item.name }}</h2>
<table><thead><tr><th>Name</th><th>Index</th></tr></thead><tbody>
<tr v-for="row in item.data" v-bind:key="row.Index">
<td>{{ row.Name }}</td>
<td>{{ row.Index }}</td>
</tr>
</tbody></table>
</div>
</div></template>
<script>
export default {
async asyncData ({$content}) {
return {
data: await $content('pres').fetch()
};
}
};
</script>
```
The browser should refresh to show the contents of the spreadsheet. If it does
not, click Refresh manually or open a new browser window.
![Nuxt Demo end of step 5](pathname:///nuxt/nuxt5.png)
6) To verify that hot loading works, open `pres.xlsx` from the `content` folder
in Excel. Add a new row to the bottom and save the file:
![Adding a new line to `pres.xlsx`](pathname:///nuxt/nuxl6.png)
The server terminal window should show a line like:
```
Updated ./content/pres.xlsx @nuxt/content 05:43:37
```
The page should automatically refresh with the new content:
![Nuxt Demo end of step 6](pathname:///nuxt/nuxt6.png)
7) Stop the server (press `CTRL+C` in the terminal window) and run
```bash
npm run generate
```
This will create a static site in the `dist` folder, which can be served with:
```bash
npx http-server dist
```
Accessing the page http://localhost:8080 will show the page contents. Verifying
the static nature is trivial: make another change in Excel and save. The page
will not change.