--- title: Bundlers pagination_prev: demos/index pagination_next: demos/grid/index sidebar_position: 8 sidebar_custom_props: skip: 1 --- import current from '/version.js'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; SheetJS predates ECMAScript modules and bundler tools like Webpack. As best practices have evolved, stress testing SheetJS libraries have revealed bugs in the respective bundlers. This demo collects various notes and provides basic examples. :::note Issues should be reported to the respective bundler projects. Typically it is considered a bundler bug if the tool cannot properly handle JS libraries. ::: ## Browserify `browserify` is compatible with the library and should "just work" with the `require` form in a main page or in a web worker: ```js var XLSX = require("xlsx"); // ... use XLSX ... ``` [After installing the module](/docs/getting-started/installation/nodejs), bundling is easy: ```bash browserify app.js > browserify.js uglifyjs browserify.js > browserify.min.js ``` Web Worker scripts can be bundled using the same approach.
Complete Example (click to show) 1) Install the tarball using a package manager:
{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
{`\
pnpm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
{`\
yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
2) Download the following files: - [`app.js`](pathname:///browserify/app.js) - [`index.html`](pathname:///browserify/index.html) - [`xlsxworker.js`](pathname:///browserify/xlsxworker.js) 3) Bundle the scripts: ```bash npx browserify app.js > browserify.js npx browserify xlsxworker.js > worker.js ``` 4) Spin up a local web server: ``` npx http-server ``` 5) Access the site http://localhost:8080/ and use the file input element to select a spreadsheet.
## Bun `bun bun` is capable of optimizing imported libraries in `node_modules`. In local testing, a bundled script can save tens of milliseconds per run.
Complete Example (click to show) 1) Install the tarball using a package manager:
{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
{`\
pnpm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
{`\
yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
2) Save the following script to `bun.js`: ```js title="bun.js" // highlight-next-line import * as XLSX from 'xlsx'; // highlight-next-line import * as fs from 'fs'; // highlight-next-line XLSX.set_fs(fs); /* fetch JSON data and parse */ const url = "https://sheetjs.com/data/executive.json"; const raw_data = await (await fetch(url)).json(); /* filter for the Presidents */ const prez = raw_data.filter((row) => row.terms.some((term) => term.type === "prez")); /* flatten objects */ const rows = prez.map((row) => ({ name: row.name.first + " " + row.name.last, birthday: row.bio.birthday })); /* generate worksheet and workbook */ const worksheet = XLSX.utils.json_to_sheet(rows); const workbook = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(workbook, worksheet, "Dates"); /* fix headers */ XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" }); /* calculate column width */ const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10); worksheet["!cols"] = [ { wch: max_width } ]; /* create an XLSX file and try to save to Presidents.xlsx */ XLSX.writeFile(workbook, "Presidents.xlsx"); ``` 3) Bundle the script with `bun bun`: ```bash bun bun bun.js ``` This procedure will generate `node_modules.bun`. 4) Run the script ```bash bun bun.js ```
## Dojo Integration details are included [in the "AMD" installation](/docs/getting-started/installation/amd#dojo-toolkit) Complete Examples are included [in the "Dojo" demo](/docs/demos/frontend/legacy#dojo-toolkit) ## esbuild The `xlsx.mjs` source file uses a subset of ES6 that `esbuild` understands and is able to transpile for older browsers. Both the `node` and `browser` platforms work out of the box.
Complete Example (click to show) 1) Install the tarball using a package manager:
{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
{`\
pnpm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
{`\
yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
2) Save the following to `esbrowser.js`: ```js title="esbrowser.js" // highlight-next-line import { utils, version, writeFileXLSX } from 'xlsx'; (async() => { /* fetch JSON data and parse */ const url = "https://sheetjs.com/data/executive.json"; const raw_data = await (await fetch(url)).json(); /* filter for the Presidents */ const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez")); /* flatten objects */ const rows = prez.map(row => ({ name: row.name.first + " " + row.name.last, birthday: row.bio.birthday })); /* generate worksheet and workbook */ const worksheet = utils.json_to_sheet(rows); const workbook = utils.book_new(); utils.book_append_sheet(workbook, worksheet, "Dates"); /* fix headers */ utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" }); /* calculate column width */ const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10); worksheet["!cols"] = [ { wch: max_width } ]; /* create an XLSX file and try to save to Presidents.xlsx */ writeFileXLSX(workbook, "Presidents.xlsx"); })(); ``` 3) Create a small HTML page that loads the script. Save to `index.html`: ```html title="index.html" ``` 4) Create bundle: ```bash npx esbuild esbrowser.js --bundle --outfile=esb.browser.js ``` 5) Start a local HTTP server, then go to http://localhost:8080/ ```bash npx http-server . ```
1) Install the tarball using a package manager:
{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
{`\
pnpm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
{`\
yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
2) Save the following to `esbnode.js`: ```js title="esbnode.js" // highlight-next-line import { set_fs, utils, version, writeFile } from 'xlsx'; // highlight-next-line import * as fs from 'fs'; // highlight-next-line set_fs(fs); (async() => { /* fetch JSON data and parse */ const url = "https://sheetjs.com/data/executive.json"; const raw_data = await (await fetch(url)).json(); /* filter for the Presidents */ const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez")); /* flatten objects */ const rows = prez.map(row => ({ name: row.name.first + " " + row.name.last, birthday: row.bio.birthday })); /* generate worksheet and workbook */ const worksheet = utils.json_to_sheet(rows); const workbook = utils.book_new(); utils.book_append_sheet(workbook, worksheet, "Dates"); /* fix headers */ utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" }); /* calculate column width */ const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10); worksheet["!cols"] = [ { wch: max_width } ]; /* create an XLSX file and try to save to Presidents.xlsx */ writeFile(workbook, "Presidents.xlsx"); })(); ``` 3) Create bundle: ```bash npx esbuild esbnode.js --bundle --platform=node --outfile=esb.node.js ``` 4) Run the bundle: ```bash node esb.node.js ```
## Parcel Parcel should play nice with SheetJS out of the box. :::warning Parcel Bug Errors of the form `Could not statically evaluate fs call` stem from a Parcel bug. Upgrade to Parcel version 1.5.0 or later. :::
Complete Example (click to show) This demo follows the [Presidents Example](/docs/getting-started/example). 1) Save the following to `index.html`: ```html title="index.html"

SheetJS export demo

``` 2) Install the SheetJS node module:
{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
{`\
pnpm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
{`\
yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
3) Run the Parcel CLI tool: ```bash npx -y parcel index.html ``` 4) Access the page listed in the output (typically `http://localhost:1234`) and click the "Click to Export!" button to generate a file.
## RequireJS [Standalone scripts](/docs/getting-started/installation/standalone) comply with AMD `define` semantics, enabling use in RequireJS out of the box. To enable use of the alias `xlsx`, the RequireJS config should set an alias in the `paths` property: ```js require.config({ baseUrl: ".", name: "app", paths: { // highlight-next-line xlsx: "xlsx.full.min" } }); // highlight-next-line require(["xlsx"], function(XLSX) { /* use XLSX here */ console.log(XLSX.version); }); ``` The [Live demo](pathname:///requirejs/requirejs.html) loads RequireJS from the CDN, uses it to load the standalone script from the SheetJS CDN, and uses the `XLSX` variable to create a button click handler that creates a workbook. The `r.js` optimizer also supports the standalone scripts. ## Rollup Rollup requires `@rollup/plugin-node-resolve` to support NodeJS modules:
Complete Example (click to show) 1) Install the tarball using a package manager:
{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} rollup @rollup/plugin-node-resolve
{`\
pnpm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} rollup @rollup/plugin-node-resolve
{`\
yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} rollup @rollup/plugin-node-resolve
2) Save the following to `index.js`: ```js title="index.js" // highlight-next-line import { utils, version, writeFileXLSX } from 'xlsx'; document.getElementById("xport").addEventListener("click", async() => { /* fetch JSON data and parse */ const url = "https://sheetjs.com/data/executive.json"; const raw_data = await (await fetch(url)).json(); /* filter for the Presidents */ const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez")); /* flatten objects */ const rows = prez.map(row => ({ name: row.name.first + " " + row.name.last, birthday: row.bio.birthday })); /* generate worksheet and workbook */ const worksheet = utils.json_to_sheet(rows); const workbook = utils.book_new(); utils.book_append_sheet(workbook, worksheet, "Dates"); /* fix headers */ utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" }); /* calculate column width */ const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10); worksheet["!cols"] = [ { wch: max_width } ]; /* create an XLSX file and try to save to Presidents.xlsx */ writeFileXLSX(workbook, "Presidents.xlsx"); }); ``` 3) Bundle the script: ```bash npx rollup index.js --plugin @rollup/plugin-node-resolve --file bundle.js --format iife ``` 4) Create a small HTML page that loads the script. Save to `index.html`: ```html title="index.html"

SheetJS Presidents Demo

``` 5) Start a local HTTP server, then go to http://localhost:8080/ ```bash npx http-server . ``` Click on "Click here to export" to generate a file.
## Snowpack Snowpack works with no caveats.
Complete Example (click to show) 1) Install the tarball using a package manager:
{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
{`\
pnpm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
{`\
yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
2) Save the following to `index.js`: ```js title="index.js" // highlight-next-line import { utils, version, writeFileXLSX } from 'xlsx'; document.getElementById("xport").addEventListener("click", async() => { /* fetch JSON data and parse */ const url = "https://sheetjs.com/data/executive.json"; const raw_data = await (await fetch(url)).json(); /* filter for the Presidents */ const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez")); /* flatten objects */ const rows = prez.map(row => ({ name: row.name.first + " " + row.name.last, birthday: row.bio.birthday })); /* generate worksheet and workbook */ const worksheet = utils.json_to_sheet(rows); const workbook = utils.book_new(); utils.book_append_sheet(workbook, worksheet, "Dates"); /* fix headers */ utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" }); /* calculate column width */ const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10); worksheet["!cols"] = [ { wch: max_width } ]; /* create an XLSX file and try to save to Presidents.xlsx */ writeFileXLSX(workbook, "Presidents.xlsx"); }); ``` 3) Create a small HTML page that loads the script. Save to `index.html`: ```html title="index.html"

SheetJS Presidents Demo

``` :::note Unlike other bundlers, Snowpack requires a full page including `HEAD` element. ::: 4) Build for production: ```bash npx snowpack build ``` 5) Start a local HTTP server, then go to http://localhost:8080/ ```bash npx http-server build/ ``` Click on "Click here to export" to generate a file.
## SWC SWC provides `spack` for bundling scripts.
Complete Example (click to show) 1) Install the dependencies using a package manager:
{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} regenerator-runtime @swc/cli @swc/core
{`\
pnpm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} regenerator-runtime @swc/cli @swc/core
{`\
yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} regenerator-runtime @swc/cli @swc/core
:::note The `regenerator-runtime` dependency is used for transpiling `fetch` and is not required if the interface code does not use `fetch` or Promises. ::: 2) Save the following to `index.js`: ```js title="index.js" import { utils, version, writeFileXLSX } from 'xlsx'; document.getElementById("xport").addEventListener("click", async() => { /* fetch JSON data and parse */ const url = "https://sheetjs.com/data/executive.json"; const raw_data = await (await fetch(url)).json(); /* filter for the Presidents */ const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez")); /* flatten objects */ const rows = prez.map(row => ({ name: row.name.first + " " + row.name.last, birthday: row.bio.birthday })); /* generate worksheet and workbook */ const worksheet = utils.json_to_sheet(rows); const workbook = utils.book_new(); utils.book_append_sheet(workbook, worksheet, "Dates"); /* fix headers */ utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" }); /* calculate column width */ const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10); worksheet["!cols"] = [ { wch: max_width } ]; /* create an XLSX file and try to save to Presidents.xlsx */ writeFileXLSX(workbook, "Presidents.xlsx"); }); ``` 3) Create an `spack.config.js` config file: ```js title="spack.config.js" const { config } = require('@swc/core/spack'); module.exports = ({ entry: { 'web': __dirname + '/index.js', }, output: { path: __dirname + '/lib' }, module: {}, }); ``` 4) Build for production: ```bash npx spack ``` This command will create the script `lib/web.js` 5) Create a small HTML page that loads the generated script: ```html title="index.html"

SheetJS Presidents Demo

``` 6) Start a local HTTP server, then go to http://localhost:8080/ ```bash npx http-server build/ ``` Click on "Click here to export" to generate a file.
## SystemJS With configuration, SystemJS supports both browser and NodeJS deployments. :::caution This demo was written against SystemJS 0.19, the most popular SystemJS version used with Angular applications. In the years since the release, Angular and other tools using SystemJS have switched to Webpack. ::: SystemJS fails by default because the library does not export anything in the web browser. The `meta` configuration option can be used to expose `XLSX`: ```js SystemJS.config({ meta: { 'xlsx': { exports: 'XLSX' // <-- tell SystemJS to expose the XLSX variable } }, map: { 'xlsx': 'https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js', 'fs': '', // <--| 'crypto': '', // <--| suppress native node modules 'stream': '' // <--| } }); SystemJS.import('main.js'); // load `main.js` ``` The `main.js` script can freely `require("xlsx")`. :::caution Web Workers Web Workers can load the SystemJS library with `importScripts`, but the imported code cannot assign the original worker's `onmessage` callback. The recommended approach is to expose a global from the required script, For example, supposing the shared name is `_cb`, the primary worker script would call the callback: ```js title="worker.js" /* main worker script */ importScripts('system.js'); SystemJS.config({ /* ... browser config ... */ }); onmessage = function(evt) { SystemJS.import('workermain.js').then(function() { _cb(evt); }); }; ``` The worker script would define and expose the function: ```js title="workermain.js" /* Loaded with SystemJS import */ var XLSX = require('xlsx'); _cb = function(evt) { /* ... do work here ... */ }; ``` ::: :::caution While SystemJS works in NodeJS, the built-in `require` should be preferred. ::: The NodeJS module main script is `xlsx/xlsx.js` and should be mapped: ```js SystemJS.config({ map: { "xlsx": "./node_modules/xlsx/xlsx.js" } }); ``` The standalone scripts require a hint that the script assigns a global: ```js SystemJS.config({ meta: { "standalone": { format: "global" } }, map: { "standalone": "xlsx.full.min.js" } }); ```
Complete Example (click to show) The [Live demo](pathname:///systemjs/systemjs.html) loads SystemJS from the CDN, uses it to load the standalone script from the SheetJS CDN and emulate a `require` implementation when loading [`main.js`](pathname:///systemjs/main.js) "View Source" works on the main HTML page and the `main.js` script. 1) Install the dependencies:
{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz systemjs@0.19`}
2) Save the following script to `SheetJSystem.js`: ```js title="SheetJSystem.js" const SystemJS = require('systemjs'); // highlight-start SystemJS.config({ map: { 'xlsx': 'node_modules/xlsx/xlsx.js', 'fs': '@node/fs', 'crypto': '@node/crypto', 'stream': '@node/stream' } }); // highlight-end SystemJS.import('xlsx').then(async function(XLSX) { /* fetch JSON data and parse */ const url = "https://sheetjs.com/data/executive.json"; const raw_data = await (await fetch(url)).json(); /* filter for the Presidents */ const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez")); /* flatten objects */ const rows = prez.map(row => ({ name: row.name.first + " " + row.name.last, birthday: row.bio.birthday })); /* generate worksheet and workbook */ const worksheet = XLSX.utils.json_to_sheet(rows); const workbook = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(workbook, worksheet, "Dates"); /* fix headers */ XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" }); /* calculate column width */ const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10); worksheet["!cols"] = [ { wch: max_width } ]; /* create an XLSX file and try to save to Presidents.xlsx */ XLSX.writeFile(workbook, "Presidents.xlsx"); }); ``` 3) Run in NodeJS: ```bash node SheetJSystem.js ``` If the demo worked, `Presidents.xlsx` will be created. :::note As it uses `fetch`, this demo requires Node 18. :::
## Vite ViteJS is compatible with SheetJS versions starting from 0.18.10.
Complete Example (click to show) 1) Create a new ViteJS project: ``` npm create vite@latest cd sheetjs-vite # (project name) npm i ``` When prompted for **Project Name**, type **`sheetjs-vite`** When prompted for **Framework**, select **`vue`** then **`vue-ts`** 2) Add the SheetJS dependency:
{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
3) Replace `src\components\HelloWorld.vue` with: ```html title="src\components\HelloWorld.vue" ``` 4) Run `npm run dev` and test functionality by opening a web browser to http://localhost:5173/ and clicking the button 5) Run `npx vite build` and verify the generated pages work by running a local web server in the `dist` folder: ``` npx http-server dist/ ``` Access http://localhost:8080 in your web browser.
:::note The [Vite section of the Content demo](/docs/demos/static/vitejs) covers asset loaders. They are ideal for static sites pulling data from sheets at build time. ::: ## Webpack The ECMAScript Module build has no `require` or `import` statements and does not use `process` or any variable that Webpack could interpret as a NodeJS feature. Various `package.json` fields have been added to appease various Webpack versions starting from the `2.x` series. :::note CommonJS and ESM Webpack bundled the CommonJS build in older versions of the library. Version `0.18.1` changed the NodeJS module package so that Webpack uses the ESM build. The ESM build does not include the codepage support library for XLS reading. [As described in the installation instructions](/docs/getting-started/installation/frameworks), the codepage dependency should be imported explicitly: ```js import * as XLSX from 'xlsx'; import * as cptable from 'xlsx/dist/cpexcel.full.mjs'; set_cptable(cptable); ``` ::: :::caution Some older webpack projects will throw an error in the browser: ``` require is not defined (xlsx.mjs) ``` This was a bug in Webpack and affected projects built with `create-react-app`. If upgrading Webpack is not feasible, explicitly import the standalone builds: ```js import * as XLSX from 'xlsx/dist/xlsx.full.min.js'; ``` :::
Complete Example (click to show) 1) Install the tarball using a package manager:
{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
{`\
pnpm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
{`\
yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
2) Save the following to `index.js`: ```js title="index.js" // highlight-next-line import { utils, version, writeFileXLSX } from 'xlsx'; document.getElementById("xport").addEventListener("click", async() => { /* fetch JSON data and parse */ const url = "https://sheetjs.com/data/executive.json"; const raw_data = await (await fetch(url)).json(); /* filter for the Presidents */ const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez")); /* flatten objects */ const rows = prez.map(row => ({ name: row.name.first + " " + row.name.last, birthday: row.bio.birthday })); /* generate worksheet and workbook */ const worksheet = utils.json_to_sheet(rows); const workbook = utils.book_new(); utils.book_append_sheet(workbook, worksheet, "Dates"); /* fix headers */ utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" }); /* calculate column width */ const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10); worksheet["!cols"] = [ { wch: max_width } ]; /* create an XLSX file and try to save to Presidents.xlsx */ writeFileXLSX(workbook, "Presidents.xlsx"); }); ``` 3) Create a small `webpack.config.js` script that writes to `index.min.js`: ```js title="webpack.config.js" module.exports = { /* entry point index.js */ entry: './index.js', /* write to index.min.js */ output: { path:__dirname, filename: './index.min.js' } } ``` 4) Build for production. The command depends on the version of webpack: **Webpack 2.x** ```bash npx webpack@2.x -p ``` **Webpack 3.x** ```bash npx webpack@3.x -p ``` :::caution The minifier that ships with Webpack 2.x does not handle `async` functions. The unminified code generated by Webpack will work for the purposes of the demo. It is strongly recommended to upgrade to a newer version of Webpack. If that is not feasible, the example should be replaced with a traditional Promise chain. ::: :::warning Pinning specific versions of webpack The webpack tooling is not designed for switching between versions. A specific version above 4.0 can be pinned by locally installing webpack and the CLI tool. ::: **Webpack 4.x** ```bash npm install --save webpack@4.x webpack-cli npx webpack --mode=production ``` **Webpack 5.x** ```bash npm install --save webpack@5.x webpack-cli npx webpack --mode=production ``` **Webpack latest** ```bash npm install --save webpack webpack-cli npx webpack --mode=production ``` 5) Create a small HTML page that loads the script. Save to `index.html`: ```html title="index.html"

SheetJS Presidents Demo

``` 6) Start a local HTTP server and go to http://localhost:8080/ ```bash npx http-server . ``` Click on "Click here to export" to generate a file.
## WMR WMR follows the same structure as Snowpack
Complete Example (click to show) 1) Install the tarball using a package manager:
{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
{`\
pnpm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
{`\
yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
2) Save the following to `index.js`: ```js title="index.js" // highlight-next-line import { utils, version, writeFileXLSX } from 'xlsx'; document.getElementById("xport").addEventListener("click", async() => { /* fetch JSON data and parse */ const url = "https://sheetjs.com/data/executive.json"; const raw_data = await (await fetch(url)).json(); /* filter for the Presidents */ const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez")); /* flatten objects */ const rows = prez.map(row => ({ name: row.name.first + " " + row.name.last, birthday: row.bio.birthday })); /* generate worksheet and workbook */ const worksheet = utils.json_to_sheet(rows); const workbook = utils.book_new(); utils.book_append_sheet(workbook, worksheet, "Dates"); /* fix headers */ utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" }); /* calculate column width */ const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10); worksheet["!cols"] = [ { wch: max_width } ]; /* create an XLSX file and try to save to Presidents.xlsx */ writeFileXLSX(workbook, "Presidents.xlsx"); }); ``` 3) Create a small HTML page that loads the script. Save to `index.html`: ```html title="index.html"

SheetJS Presidents Demo

``` 4) Build for production: ```bash npx wmr build ``` 5) Start a local HTTP server in `dist` folder and go to http://localhost:8080/ ```bash npx http-server dist/ ``` Click on "Click here to export" to generate a file.