--- title: ViteJS pagination_prev: demos/net/index pagination_next: demos/mobile/index sidebar_custom_props: type: bundler --- import current from '/version.js'; :::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 = `
${data.map(row => JSON.stringify(row)).join("\n")}
`; ``` ### 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 = `
${wsname}
${csv}
`; ``` ## 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 : ```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" ``` 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" ``` 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.