forked from sheetjs/docs.sheetjs.com
		
	
		
			
	
	
		
			305 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			305 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| 
								 | 
							
								---
							 | 
						||
| 
								 | 
							
								title: Webpack
							 | 
						||
| 
								 | 
							
								pagination_prev: demos/net/index
							 | 
						||
| 
								 | 
							
								pagination_next: demos/mobile/index
							 | 
						||
| 
								 | 
							
								sidebar_custom_props:
							 | 
						||
| 
								 | 
							
								  type: bundler
							 | 
						||
| 
								 | 
							
								---
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import current from '/version.js';
							 | 
						||
| 
								 | 
							
								import CodeBlock from '@theme/CodeBlock';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:::note
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This demo covers static asset imports. For processing files in the browser, the
							 | 
						||
| 
								 | 
							
								["Bundlers" demo](/docs/demos/frontend/bundler#webpack) includes an example.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:::
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The [NodeJS Module](/docs/getting-started/installation/nodejs) can be imported
							 | 
						||
| 
								 | 
							
								from Webpack loader scripts.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Webpack 5 Asset Module
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Webpack 5 supports asset modules. With a special option, the loader will receive
							 | 
						||
| 
								 | 
							
								NodeJS Buffers that can be parsed. The dev server will even watch the files and
							 | 
						||
| 
								 | 
							
								reload the page in development mode!
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The following diagram depicts the workbook waltz:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```mermaid
							 | 
						||
| 
								 | 
							
								flowchart LR
							 | 
						||
| 
								 | 
							
								  file[(workbook\nfile)]
							 | 
						||
| 
								 | 
							
								  subgraph SheetJS operations
							 | 
						||
| 
								 | 
							
								    buffer(NodeJS\nBuffer)
							 | 
						||
| 
								 | 
							
								    aoo(array of\nobjects)
							 | 
						||
| 
								 | 
							
								  end
							 | 
						||
| 
								 | 
							
								  html{{HTML\nTABLE}}
							 | 
						||
| 
								 | 
							
								  file --> |webpack.config.js\ncustom rule| buffer
							 | 
						||
| 
								 | 
							
								  buffer --> |sheetjs-loader.js\ncustom plugin| aoo
							 | 
						||
| 
								 | 
							
								  aoo --> |src/index.js\nfrontend code| html
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Webpack Config
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								A special rule should be added to `module.rules`:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js title="webpack.config.js"
							 | 
						||
| 
								 | 
							
								// ...
							 | 
						||
| 
								 | 
							
								module.exports = {
							 | 
						||
| 
								 | 
							
								  // ...
							 | 
						||
| 
								 | 
							
								  module: {
							 | 
						||
| 
								 | 
							
								    rules: [
							 | 
						||
| 
								 | 
							
								      // highlight-start
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        /* `test` matches file extensions */
							 | 
						||
| 
								 | 
							
								        test: /\.(numbers|xls|xlsx|xlsb)/,
							 | 
						||
| 
								 | 
							
								        /* use the loader script */
							 | 
						||
| 
								 | 
							
								        use: [ { loader: './sheetjs-loader' } ]
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      // highlight-end
							 | 
						||
| 
								 | 
							
								    ]
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Hot Module Replacement enables reloading when files are updated:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js title="webpack.config.js"
							 | 
						||
| 
								 | 
							
								// ...
							 | 
						||
| 
								 | 
							
								module.exports = {
							 | 
						||
| 
								 | 
							
								  // ...
							 | 
						||
| 
								 | 
							
								  // highlight-start
							 | 
						||
| 
								 | 
							
								  devServer: {
							 | 
						||
| 
								 | 
							
								    static: './dist',
							 | 
						||
| 
								 | 
							
								    hot: true,
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  // highlight-end
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								It is strongly recommended to add an alias to simplify imports:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js title="webpack.config.js"
							 | 
						||
| 
								 | 
							
								// ...
							 | 
						||
| 
								 | 
							
								module.exports = {
							 | 
						||
| 
								 | 
							
								  // ...
							 | 
						||
| 
								 | 
							
								  // highlight-start
							 | 
						||
| 
								 | 
							
								  resolve: {
							 | 
						||
| 
								 | 
							
								    alias: {
							 | 
						||
| 
								 | 
							
								      /* `~` root of the project */
							 | 
						||
| 
								 | 
							
								      "~": __dirname
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  },
							 | 
						||
| 
								 | 
							
								  // highlight-end
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### SheetJS Loader
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The SheetJS loader script must export a `raw` property that is set to `true`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The base export is expected to be the loader function. That function receives
							 | 
						||
| 
								 | 
							
								the file contents as a Buffer, which can be parsed with `XLSX.read`. Typically
							 | 
						||
| 
								 | 
							
								this script is CommonJS so the `require` form should be used.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The loader in this demo will parse the first worksheet:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js title="sheetjs-loader.js"
							 | 
						||
| 
								 | 
							
								const XLSX = require("xlsx");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function loader(content) {
							 | 
						||
| 
								 | 
							
								  /* since `loader.raw` is true, `content` is a Buffer */
							 | 
						||
| 
								 | 
							
								  const wb = XLSX.read(content);
							 | 
						||
| 
								 | 
							
								  /* pull data from first worksheet */
							 | 
						||
| 
								 | 
							
								  var data = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
							 | 
						||
| 
								 | 
							
								  return `export default JSON.parse('${JSON.stringify(data)}')`;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								/* ensure the function receives a Buffer */
							 | 
						||
| 
								 | 
							
								loader.raw = true;
							 | 
						||
| 
								 | 
							
								module.exports = loader;
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Asset Imports
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Spreadsheets can be imported using the plugin.  Assuming `pres.xlsx` is stored
							 | 
						||
| 
								 | 
							
								in the `data` subfolder, `~/data/pres.xlsx` can be imported from any script:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js title="src/index.js"
							 | 
						||
| 
								 | 
							
								import data from '~/data/pres.xlsx';
							 | 
						||
| 
								 | 
							
								/* `data` is an array of objects from data/pres.xlsx */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const elt = document.createElement('div');
							 | 
						||
| 
								 | 
							
								elt.innerHTML = "<table><tr><th>Name</th><th>Index</th></tr>" +
							 | 
						||
| 
								 | 
							
								  data.map((row) => `<tr>
							 | 
						||
| 
								 | 
							
								    <td>${row.Name}</td>
							 | 
						||
| 
								 | 
							
								    <td>${row.Index}</td>
							 | 
						||
| 
								 | 
							
								  </tr>`).join("") +
							 | 
						||
| 
								 | 
							
								"</table>";
							 | 
						||
| 
								 | 
							
								document.body.appendChild(elt);
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Webpack 5 Demo
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:::note
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This demo was last tested on 2023 May 24 against Webpack 5.84.0
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:::
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Initial Setup
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								0) Create a new skeleton project:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```bash
							 | 
						||
| 
								 | 
							
								mkdir sheetjs-wp5
							 | 
						||
| 
								 | 
							
								cd sheetjs-wp5
							 | 
						||
| 
								 | 
							
								npm init -y
							 | 
						||
| 
								 | 
							
								npm install webpack@5.84.0 webpack-cli@5.1.1 webpack-dev-server@4.15.0 --save
							 | 
						||
| 
								 | 
							
								mkdir -p dist
							 | 
						||
| 
								 | 
							
								mkdir -p src
							 | 
						||
| 
								 | 
							
								mkdir -p data
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								1) Install the SheetJS NodeJS module:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								<CodeBlock language="bash">{`\
							 | 
						||
| 
								 | 
							
								npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
							 | 
						||
| 
								 | 
							
								</CodeBlock>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								2) Save the following to `dist/index.html`:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```html title="dist/index.html"
							 | 
						||
| 
								 | 
							
								<!DOCTYPE html>
							 | 
						||
| 
								 | 
							
								<html>
							 | 
						||
| 
								 | 
							
								  <head>
							 | 
						||
| 
								 | 
							
								    <title>SheetJS + Webpack 5</title>
							 | 
						||
| 
								 | 
							
								  </head>
							 | 
						||
| 
								 | 
							
								  <body>
							 | 
						||
| 
								 | 
							
								   <script src="main.js"></script>
							 | 
						||
| 
								 | 
							
								  </body>
							 | 
						||
| 
								 | 
							
								</html>
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								3) Save the following to `src/index.js`:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js title="src/index.js"
							 | 
						||
| 
								 | 
							
								import data from '~/data/pres.xlsx';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const elt = document.createElement('div');
							 | 
						||
| 
								 | 
							
								elt.innerHTML = "<table><tr><th>Name</th><th>Index</th></tr>" +
							 | 
						||
| 
								 | 
							
								  data.map((row) => `<tr>
							 | 
						||
| 
								 | 
							
								    <td>${row.Name}</td>
							 | 
						||
| 
								 | 
							
								    <td>${row.Index}</td>
							 | 
						||
| 
								 | 
							
								  </tr>`).join("") +
							 | 
						||
| 
								 | 
							
								"</table>";
							 | 
						||
| 
								 | 
							
								document.body.appendChild(elt);
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								4) Save the following to `webpack.config.js`:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js title="webpack.config.js"
							 | 
						||
| 
								 | 
							
								const path = require('path');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = {
							 | 
						||
| 
								 | 
							
								  entry: './src/index.js',
							 | 
						||
| 
								 | 
							
								  output: {
							 | 
						||
| 
								 | 
							
								    filename: 'main.js',
							 | 
						||
| 
								 | 
							
								    path: path.resolve(__dirname, 'dist'),
							 | 
						||
| 
								 | 
							
								  },
							 | 
						||
| 
								 | 
							
								  devServer: {
							 | 
						||
| 
								 | 
							
								    static: './dist',
							 | 
						||
| 
								 | 
							
								    hot: true,
							 | 
						||
| 
								 | 
							
								  },
							 | 
						||
| 
								 | 
							
								  resolve: {
							 | 
						||
| 
								 | 
							
								    alias: {
							 | 
						||
| 
								 | 
							
								      "~": __dirname
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  },
							 | 
						||
| 
								 | 
							
								  module: {
							 | 
						||
| 
								 | 
							
								    rules: [
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        test: /\.(numbers|xls|xlsx|xlsb)/,
							 | 
						||
| 
								 | 
							
								        use: [ { loader: './sheetjs-loader' } ]
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    ]
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								5) Save the following to `sheetjs-loader.js`:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js title="sheetjs-loader.js"
							 | 
						||
| 
								 | 
							
								const XLSX = require("xlsx");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function loader(content) {
							 | 
						||
| 
								 | 
							
								  /* since `loader.raw` is true, `content` is a Buffer */
							 | 
						||
| 
								 | 
							
								  const wb = XLSX.read(content);
							 | 
						||
| 
								 | 
							
								  /* pull data from first worksheet */
							 | 
						||
| 
								 | 
							
								  var data = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
							 | 
						||
| 
								 | 
							
								  return `export default JSON.parse('${JSON.stringify(data)}')`;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								/* ensure the function receives a Buffer */
							 | 
						||
| 
								 | 
							
								loader.raw = true;
							 | 
						||
| 
								 | 
							
								module.exports = loader;
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								6) Download <https://sheetjs.com/pres.xlsx> and save to the `data` folder:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```bash
							 | 
						||
| 
								 | 
							
								curl -L -o data/pres.xlsx https://sheetjs.com/pres.xlsx
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Live Reload Test
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								7) Open the test file `data/pres.xlsx` in a spreadsheet editor like Excel.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								8) Start the development server:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```bash
							 | 
						||
| 
								 | 
							
								npx webpack serve --mode=development
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The terminal will print URLs for the development server:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								<i> [webpack-dev-server] Project is running at:
							 | 
						||
| 
								 | 
							
								<i> [webpack-dev-server] Loopback: http://localhost:8080/
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								9) Open the `Loopback` address (`http://localhost:8080`) in a web browser.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								It should display a table of Presidents with "Name" and "Index" columns
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								10) Add a new row to the spreadsheet and save the file.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Upon saving, the page should refresh with the new data.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Static Site Test
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								11) Stop Webpack and build the site:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```bash
							 | 
						||
| 
								 | 
							
								npx webpack --mode=production
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The final site will be placed in the `dist` folder.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								12) Start a local web server to host the `dist` folder:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```bash
							 | 
						||
| 
								 | 
							
								npx http-server dist
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The command will print a list of URLs.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								13) Open one of the URLs printed in the previous step (`http://localhost:8080`)
							 | 
						||
| 
								 | 
							
								and confirm that the same data is displayed.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								To verify that the page is independent of the spreadsheet, make some changes to
							 | 
						||
| 
								 | 
							
								the file and save.  The page will not automatically update.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								To verify that the data was added to the page, append `main.js` to the URL
							 | 
						||
| 
								 | 
							
								(`http://localhost:8080/main.js`) and view the source.  The source will include
							 | 
						||
| 
								 | 
							
								president names.  It will not include SheetJS library references!
							 |