Skip to main content

Bundling Sheets with SWC

SWC1 is a JS toolchain. SWC provides spack (formally called "swcpack") for bundling scripts.

SheetJS is a JavaScript library for reading and writing data from spreadsheets.

This demo uses spack and SheetJS to export data. We'll explore how to bundle SheetJS in a site using spack and how to export data to spreadsheets.

This demo focuses on integration details with the spack bundler.

The demos follow the "Export Tutorial", which covers SheetJS library usage in more detail.

Tested Deployments

This demo was tested in the following environments:


Integration Details

The "Frameworks" section covers installation with Yarn and other package managers.

After installing the SheetJS module in a SWC spack project, import statements can load relevant parts of the library.

Projects that import data will use methods such as read2 to parse workbooks and sheet_to_json3 to generate usable data from files. As sheet_to_json is part of the utils object, the required import is:

import { read, utils } from 'xlsx';

Projects that export data will use methods such as json_to_sheet4 to generate worksheets and writeFile5 to export files. As json_to_sheet is part of the utils object, the required import is:

import { utils, writeFile } from 'xlsx';

When this demo was tested against the @swc/[email protected], spack crashed:

thread '<unnamed>' panicked at 'cannot access a scoped thread local variable without calling `set` first',

This is a bug in SWC

Until the bug is fixed, it is strongly recommended to use @swc/[email protected].

Complete Example

0) Initialize a new project:

mkdir sheetjs-spack
cd sheetjs-spack
npm init -y

1) Install the dependencies using a package manager:

yarn add regenerator-runtime @swc/cli @swc/[email protected]

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:

import { utils, version, writeFileXLSX } from 'xlsx';

document.getElementById("xport").addEventListener("click", async() => {
/* fetch JSON data and parse */
const url = "";
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"));

/* sort by first presidential term */
prez.forEach(row => row.start = row.terms.find(term => term.type === "prez").start);
prez.sort((l,r) => l.start.localeCompare(r.start));

/* flatten objects */
const rows = => ({
name: + " " +,

/* 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,, 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:

module.exports = ({
entry: {
'web': __dirname + '/index.js',
output: {
path: __dirname + '/lib'
module: {},

4) Build for production:

npx spack

This command will create the script lib/web.js

5) Create a small HTML page that loads the generated script:

<!DOCTYPE html>
<html lang="en">
<h1>SheetJS Presidents Demo</h1>
<button id="xport">Click here to export</button>
<script src="lib/web.js"></script>

6) Start a local HTTP server, then go to http://localhost:8080/

npx http-server .

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