---
title: ViteJS
pagination_prev: demos/net/index
pagination_next: demos/mobile/index
sidebar_custom_props:
  type: bundler
---
import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';
:::note
This demo covers static asset imports. For processing files in the browser, the
["Bundlers" demo](/docs/demos/frontend/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, the library
will be included in the final bundle.
:::
### 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!
The following diagram depicts the workbook waltz:
```mermaid
flowchart LR
  file[(workbook\nfile)]
  subgraph SheetJS operations
    buffer(NodeJS\nBuffer)
    aoo(array of\nobjects)
  end
  html{{HTML\nTABLE}}
  file --> |vite.config.js\ncustom plugin| buffer
  buffer --> |vite.config.js\ncustom plugin| aoo
  aoo --> |main.js\nfrontend code| html
```
```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 = `
${data.map(row => JSON.stringify(row)).join("\n")}
    | Name | Index | 
|---|
    
      | {{row.Name}} | {{row.Index}} | 
  
```
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"
  
    | Name | Index | 
|---|
    
      | {{row.Name}} | {{row.Index}} | 
  
```
10) Stop the dev server and build the site
```bash
npm run build
npx http-server dist/
```
The terminal will display a URL ( `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.