Skip to main content

Bundling Sheets with Webpack

Webpack is a module bundler.

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

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

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

This demo focuses on integration details with the Webpack 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:

VersionDateRequired Workarounds
2.7.02024-03-16Import xlsx/dist/xlsx.full.min.js
3.12.02024-03-16Import xlsx/dist/xlsx.full.min.js
4.47.02024-03-16Downgrade NodeJS (tested v16.20.2)
5.90.32024-03-16

Integration Details

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

After installing the SheetJS module in a Webpack 5 project, import statements and require expressions can load relevant parts of the library.

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.

Projects that import data will use methods such as read1 to parse workbooks and sheet_to_json2 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_sheet3 to generate worksheets and writeFile4 to export files. As json_to_sheet is part of the utils object, the required import is:

import { utils, writeFile } from 'xlsx';

The writeFileXLSX function is a small version of writeFile that exclusively supports generating XLSX spreadsheets. When the application only allows XLSX exports, writeFileXLSX will reduce the final page size.

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 CommonJS build includes the codepage support library for XLS processing.

The ESM build does not include the codepage support library. As described in the installation instructions, the codepage dependency should be imported explicitly:

import * as XLSX from 'xlsx';
import * as cptable from 'xlsx/dist/cpexcel.full.mjs';
set_cptable(cptable);

Legacy Webpack

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 script:

import * as XLSX from 'xlsx/dist/xlsx.full.min.js';

Complete Example

  1. Initialize a new project:
mkdir sheetjs-webpack
cd sheetjs-webpack
npm init -y
  1. Install the tarball using a package manager:
yarn add https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz
  1. Save the following to index.js:
index.js
import { utils, version, writeFileXLSX } from 'xlsx';

document.getElementById("xport").addEventListener("click", function() {
/* fetch JSON data and parse */
var url = "https://docs.sheetjs.com/executive.json";
fetch(url).then(function(res) { return res.json(); }).then(function(raw_data) {

/* filter for the Presidents */
var prez = raw_data.filter(function(row) { return row.terms.some(function(term) { return term.type === "prez"; }); });

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

/* flatten objects */
var rows = prez.map(function(row) { return {
name: row.name.first + " " + row.name.last,
birthday: row.bio.birthday
}; });

/* generate worksheet and workbook */
var worksheet = utils.json_to_sheet(rows);
var 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 */
var max_width = rows.reduce(function(w, r) { return 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");
});
});

The minifier that ships with Webpack 2.x does not handle async functions or ES6 arrow functions.

To demonstrate compatibility with older versions of Webpack, the index.js script uses normal functions and traditional Promise chains.

  1. Create a small webpack.config.js script that writes to index.min.js:
webpack.config.js
module.exports = {
/* entry point index.js */
entry: './index.js',

/* write to index.min.js */
output: { path:__dirname, filename: './index.min.js' }
}
  1. Build for production. The command depends on the version of webpack:
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

Webpack 4 is incompatible with Node 18+. It will elicit the following error:

Error: error:0308010C:digital envelope routines::unsupported

When this demo was last tested, NodeJS was locally downgraded to 16.20.2

npm i --save [email protected] [email protected]
npx webpack --mode=production

Webpack 5.x

npm i --save [email protected] [email protected]
npx webpack --mode=production

Webpack latest

npm i --save webpack webpack-cli
npx webpack --mode=production
  1. Create a small HTML page that loads the script. Save to index.html:
index.html
<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
<h1>SheetJS Presidents Demo</h1>
<button id="xport">Click here to export</button>
<script src="./index.min.js"></script>
</body>
</html>
  1. Start a local HTTP server:
npx http-server .
  1. Load the displayed URL (typically http://localhost:8080/) in a web browser.

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

Miscellany

Footnotes

  1. See read in "Reading Files"

  2. See sheet_to_json in "Utilities"

  3. See json_to_sheet in "Utilities"

  4. See writeFile in "Writing Files"