docs.sheetjs.com/docz/docs/03-demos/01-frontend/19-bundler/index.md
2023-10-21 21:42:08 -04:00

17 KiB

title pagination_prev pagination_next sidebar_position sidebar_custom_props
Bundlers demos/index demos/grid/index 19
skip
1

import current from '/version.js'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common';

SheetJS predates ECMAScript modules and most bundler tools. As best practices have evolved, stress testing SheetJS libraries have revealed bugs in bundlers and other tools. This demo collects various notes and provides basic examples.

:::note pass

Issues should be reported to the respective bundler projects. Typically it is considered a bundler bug if the tool cannot properly handle JS libraries.

:::

The following tools are covered in separate pages:

    {useCurrentSidebarCategory().items.filter(item => !item?.customProps?.skip).map((item, index) => { const listyle = (item.customProps?.icon) ? { listStyleImage: `url("${item.customProps.icon}")` } : {}; return (
  • {item.label}{item.customProps?.summary && (" - " + item.customProps.summary)}
  • ); })}

Browserify

The exposition has been moved to a separate page.

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)

:::note

This demo was last tested on 2023 May 07 against Bun 0.5.9

:::

  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`}
  1. Save the following script to 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");
  1. Bundle the script with bun bun:
bun bun bun.js

This procedure will generate node_modules.bun.

  1. Run the script
bun bun.js

Dojo

Integration details are included in the "AMD" installation

Complete Examples are included in the "Dojo" demo

esbuild

The exposition has been moved to a separate page.

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)

:::note

This demo was last tested on 2023 May 07 against parcel 2.8.3

:::

This demo follows the Presidents Example.

  1. Save the following to index.html:
<body>
<h3>SheetJS <span id="vers"></span> export demo</h3>
<button id="xport">Click to Export!</button>
<!-- the script tag must be marked as `type="module"` -->
<!-- highlight-next-line -->
<script type="module">
// ESM-style import from "xlsx"
// highlight-next-line
import { utils, version, writeFileXLSX } from 'xlsx';

document.getElementById("vers").innerText = version;
document.getElementById("xport").onclick = 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");
};
</script>
<body>
  1. 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`}
  1. Run the Parcel CLI tool:
npx -y parcel@2.8.3 index.html
  1. Access the page listed in the output (typically http://localhost:1234) and click the "Click to Export!" button to generate a file.

RequireJS

The exposition has been moved to a separate page.

Rollup

Rollup requires @rollup/plugin-node-resolve to support NodeJS modules:

Complete Example (click to show)

:::note

This demo was last tested on 2023 May 07 against Rollup 3.21.5

:::

  1. Install the tarball using a package manager:
{`\ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} rollup@3.21.5 @rollup/plugin-node-resolve {`\ pnpm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} rollup@3.21.5 @rollup/plugin-node-resolve {`\ yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} rollup@3.21.5 @rollup/plugin-node-resolve
  1. Save the following to 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");
});
  1. Bundle the script:
npx rollup index.js --plugin @rollup/plugin-node-resolve --file bundle.js --format iife
  1. Create a small HTML page that loads the script. Save to index.html:
<!DOCTYPE html>
<html lang="en">
  <head></head>
  <body>
    <h1>SheetJS Presidents Demo</h1>
    <button id="xport">Click here to export</button>
    <script type="module" src="./bundle.js"></script>
  </body>
</html>
  1. Start a local HTTP server, then go to http://localhost:8080/
npx http-server .

Click on "Click here to export" to generate a file.

Snowpack

Snowpack works with no caveats.

Complete Example (click to show)

:::note

This demo was last tested on 2023 May 07 against Snowpack 3.8.8

:::

  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`}
  1. Save the following to 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");
});
  1. Create a small HTML page that loads the script. Save to index.html:
<!DOCTYPE html>
<html lang="en">
  <head></head>
  <body>
    <h1>SheetJS Presidents Demo</h1>
    <button id="xport">Click here to export</button>
    <script type="module" src="./index.js"></script>
  </body>
</html>

:::note pass

Unlike other bundlers, Snowpack requires a full page including HEAD element.

:::

  1. Build for production:
npx snowpack@3.8.8 build
  1. Start a local HTTP server, then go to http://localhost:8080/
npx http-server build/

Click on "Click here to export" to generate a file.

SWC

The exposition has been moved to a separate page.

SystemJS

The exposition has been moved to a separate page.

Vite

ViteJS is compatible with SheetJS versions starting from 0.18.10.

Complete Example (click to show)

:::note

This demo was last tested on 2023 May 07 against ViteJS 4.3.5

:::

  1. Create a new ViteJS project:
npm create vite@latest sheetjs-vite -- --template vue-ts
cd sheetjs-vite
npm i
  1. Add the SheetJS dependency:

{\ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz}

  1. Replace src\components\HelloWorld.vue with:
<script setup lang="ts">
import { version, utils, writeFileXLSX } from 'xlsx';

interface President {
  terms: { "type": "prez" | "viceprez"; }[];
  name: { first: string; last: string; }
  bio: { birthday: string; }
}

async function xport() {
/* fetch JSON data and parse */
const url = "https://sheetjs.com/data/executive.json";
const raw_data: President[] = 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");
}

</script>

<template>
  <button type="button" @click="xport">Export with SheetJS version {{ version }}</button>
</template>
  1. Run npm run dev and test functionality by opening a web browser to http://localhost:5173/ and clicking the button

  2. 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 and click the export button.

:::note pass

The Vite section of the Content demo covers asset loaders. They are ideal for static sites pulling data from sheets at build time.

:::

Webpack

The exposition has been moved to a separate page.

WMR

WMR works with no caveats.

Complete Example (click to show)

:::note

This demo was last tested on 2023 May 07 against WMR 3.8.0

:::

  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`}
  1. Save the following to 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");
});
  1. Create a small HTML page that loads the script. Save to index.html:
<!DOCTYPE html>
<html lang="en">
  <head></head>
  <body>
    <h1>SheetJS Presidents Demo</h1>
    <button id="xport">Click here to export</button>
    <script type="module" src="./index.js"></script>
  </body>
</html>
  1. Build for production:
npx wmr@3.8.0 build
  1. Start a local HTTP server in dist folder and go to http://localhost:8080/
npx http-server dist/

Click on "Click here to export" to generate a file.