forked from sheetjs/docs.sheetjs.com
		
	swcMinify
This commit is contained in:
		
							parent
							
								
									ae9e15716b
								
							
						
					
					
						commit
						b8eeab685c
					
				| @ -17,7 +17,7 @@ to load data from spreadsheets. | ||||
| 
 | ||||
| :::note | ||||
| 
 | ||||
| This was tested against `lume v1.12.0` on 2022 October 4. | ||||
| This was tested against `lume v1.14.2` on 2022 December 27. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| @ -28,7 +28,7 @@ This was tested against `lume v1.12.0` on 2022 October 4. | ||||
| ```bash | ||||
| mkdir -p sheetjs-lume | ||||
| cd sheetjs-lume | ||||
| deno run -A https://deno.land/x/lume/init.ts | ||||
| deno run -Ar https://deno.land/x/lume/init.ts | ||||
| ``` | ||||
| 
 | ||||
| When prompted, enter the following options: | ||||
| @ -132,7 +132,7 @@ The following query pulls the `Name` and `Index` fields from each row: | ||||
|   allPresXlsxSheet1 { # "all" followed by type | ||||
|     edges { | ||||
|       node { # each line in this block should be a field in the data | ||||
|         Name  | ||||
|         Name | ||||
|         Index | ||||
|       } | ||||
|     } | ||||
| @ -157,6 +157,8 @@ overridden through a `package.json` override in the latest versions of NodeJS: | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| #### GatsbyJS Demo | ||||
| 
 | ||||
| <details><summary><b>Complete Example</b> (click to show)</summary> | ||||
| 
 | ||||
| :::note | ||||
| @ -471,7 +473,7 @@ ${csv} | ||||
| 
 | ||||
| :::note | ||||
| 
 | ||||
| This was tested against `next v12.2.5` on 2022 August 16. | ||||
| This was tested against `next v13.1.1` on 2022 December 28. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| @ -500,7 +502,7 @@ export default function Index({html, type}) { return ( | ||||
| ); } | ||||
| ``` | ||||
| 
 | ||||
| :::warning | ||||
| :::warning Reading and writing files during the build process | ||||
| 
 | ||||
| `fs` cannot be statically imported from the top level in NextJS pages.  The | ||||
| dynamic import must happen within a lifecycle function.  For example: | ||||
| @ -523,6 +525,20 @@ export async function getServerSideProps() { | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| :::caution Next 13+ and SWC | ||||
| 
 | ||||
| Next 13 switched to the SWC minifier. There are known issues with the minifier. | ||||
| Until those issues are resolved, SWC should be disabled in `next.config.js`: | ||||
| 
 | ||||
| ```js title="next.config.js" | ||||
| module.exports = { | ||||
| // highlight-next-line | ||||
|   swcMinify: false | ||||
| }; | ||||
| ``` | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| #### Demo | ||||
| 
 | ||||
| <details><summary><b>Complete Example</b> (click to show)</summary> | ||||
| @ -530,13 +546,13 @@ export async function getServerSideProps() { | ||||
| 0) Disable NextJS telemetry: | ||||
| 
 | ||||
| ```js | ||||
| npx next telemetry disable | ||||
| npx next@13.1.1 telemetry disable | ||||
| ``` | ||||
| 
 | ||||
| Confirm it is disabled by running | ||||
| 
 | ||||
| ```js | ||||
| npx next telemetry status | ||||
| npx next@13.1.1 telemetry status | ||||
| ``` | ||||
| 
 | ||||
| 1) Set up folder structure.  At the end, a `pages` folder with a `sheets` | ||||
| @ -556,7 +572,7 @@ curl -LO https://docs.sheetjs.com/next/sheetjs.xlsx | ||||
| 3) Install dependencies: | ||||
| 
 | ||||
| ```bash | ||||
| npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz next@12.2.5 | ||||
| npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz next@13.1.1 | ||||
| ``` | ||||
| 
 | ||||
| 4) Download test scripts: | ||||
| @ -594,7 +610,7 @@ cd ../.. | ||||
| 5) Test the deployment: | ||||
| 
 | ||||
| ```bash | ||||
| npx next@12.2.5 | ||||
| npx next@13.1.1 | ||||
| ``` | ||||
| 
 | ||||
| Open a web browser and access: | ||||
| @ -613,19 +629,19 @@ The individual worksheets are available at | ||||
| 6) Stop the server and run a production build: | ||||
| 
 | ||||
| ```bash | ||||
| npx next@12.2.5 build | ||||
| npx next@13.1.1 build | ||||
| ``` | ||||
| 
 | ||||
| The final output will show a list of the routes and types: | ||||
| 
 | ||||
| ``` | ||||
| Route (pages)                              Size     First Load JS | ||||
| ┌ ○ /                                      551 B          81.7 kB | ||||
| ├ ○ /404                                   194 B          77.2 kB | ||||
| ├ λ /getServerSideProps                    602 B          81.7 kB | ||||
| ├ ● /getStaticPaths                        2.7 kB         83.8 kB | ||||
| ├ ● /getStaticProps                        600 B          81.7 kB | ||||
| └ ● /sheets/[id] (312 ms)                  580 B          81.7 kB | ||||
| ┌ ○ /                                      541 B          77.4 kB | ||||
| ├ ○ /404                                   181 B          73.7 kB | ||||
| ├ λ /getServerSideProps                    594 B          77.4 kB | ||||
| ├ ● /getStaticPaths                        2.56 kB        79.4 kB | ||||
| ├ ● /getStaticProps                        591 B          77.4 kB | ||||
| └ ● /sheets/[id] (447 ms)                  569 B          77.4 kB | ||||
|     ├ /sheets/0 | ||||
|     ├ /sheets/1 | ||||
|     └ /sheets/2 | ||||
| @ -638,7 +654,7 @@ worksheets in the file.  `/getServerSideProps` is server-rendered. | ||||
| 7) Try to build a static site: | ||||
| 
 | ||||
| ```bash | ||||
| npx next@12.2.5 export | ||||
| npx next@13.1.1 export | ||||
| ``` | ||||
| 
 | ||||
| :::note The static export will fail! | ||||
| @ -648,17 +664,17 @@ is still server-rendered. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| 8) Remove `pages/getServerSideProps.js` and rebuild with `npx next@12.2.5 build` | ||||
| 8) Remove `pages/getServerSideProps.js` and rebuild with `npx next@13.1.1 build` | ||||
| 
 | ||||
| Inspecting the output, there should be no lines with the `λ` symbol: | ||||
| 
 | ||||
| ``` | ||||
| Route (pages)                              Size     First Load JS | ||||
| ┌ ○ /                                      551 B          81.7 kB | ||||
| ├ ○ /404                                   194 B          77.2 kB | ||||
| ├ ● /getStaticPaths                        2.7 kB         83.8 kB | ||||
| ├ ● /getStaticProps                        600 B          81.7 kB | ||||
| └ ● /sheets/[id] (312 ms)                  580 B          81.7 kB | ||||
| ┌ ○ /                                      541 B          77.4 kB | ||||
| ├ ○ /404                                   181 B          73.7 kB | ||||
| ├ ● /getStaticPaths                        2.56 kB        79.4 kB | ||||
| ├ ● /getStaticProps                        591 B          77.4 kB | ||||
| └ ● /sheets/[id] (459 ms)                  569 B          77.4 kB | ||||
|     ├ /sheets/0 | ||||
|     ├ /sheets/1 | ||||
|     └ /sheets/2 | ||||
| @ -667,7 +683,7 @@ Route (pages)                              Size     First Load JS | ||||
| 9) Generate the static site: | ||||
| 
 | ||||
| ```bash | ||||
| npx next@12.2.5 export | ||||
| npx next@13.1.1 export | ||||
| ``` | ||||
| 
 | ||||
| The static site will be written to the `out` subfolder, which can be hosted with | ||||
|  | ||||
| @ -6,7 +6,60 @@ Parsing and writing large spreadsheets takes time. During the process, if the | ||||
| SheetJS library is running in the web browser, the website may freeze. | ||||
| 
 | ||||
| Workers provide a way to off-load the hard work so that the website does not | ||||
| freeze during processing. | ||||
| freeze during processing. The work is still performed locally.  No data is sent | ||||
| to a remote server. | ||||
| 
 | ||||
| The following diagrams show the normal and Web Worker flows when exporting a | ||||
| dataset. The regions with a red background mark when the browser is frozen. | ||||
| 
 | ||||
| <table><thead><tr><th>Normal Export</th><th>Web Worker Export</th></tr> | ||||
|   </thead><tbody><tr><td> | ||||
| 
 | ||||
| ```mermaid | ||||
| sequenceDiagram | ||||
|   autonumber | ||||
|   actor User | ||||
|   participant Page | ||||
|   User->>Page: click button | ||||
|   rect rgba(255,0,0,.2) | ||||
|     activate Page | ||||
|     Note over Page: collect dataset | ||||
|     Note over Page: generate workbook | ||||
|     Note over Page: create file | ||||
|     Note over Page: setup download | ||||
|   end | ||||
|   Page->>User: download workbook | ||||
|   deactivate Page | ||||
| ``` | ||||
| 
 | ||||
| </td><td> | ||||
| 
 | ||||
| ```mermaid | ||||
| sequenceDiagram | ||||
|   autonumber | ||||
|   actor User | ||||
|   participant Page | ||||
|   participant Worker | ||||
|   User->>Page: click button | ||||
|   rect rgba(255,0,0,.2) | ||||
|     activate Page | ||||
|     Note over Page: collect dataset | ||||
|     Page->>Worker: transfer dataset | ||||
|   end | ||||
|   deactivate Page | ||||
|   activate Worker | ||||
|   Note over Worker: generate workbook | ||||
|   Note over Worker: create file | ||||
|   Note over Worker: setup download | ||||
|   Worker->>Page: URL to download | ||||
|   deactivate Worker | ||||
|   activate Page | ||||
|   Page->>User: download workbook | ||||
|   deactivate Page | ||||
| ``` | ||||
| 
 | ||||
| </td></tr></tbody></table> | ||||
| 
 | ||||
| 
 | ||||
| :::note Browser Compatibility | ||||
| 
 | ||||
| @ -17,7 +70,7 @@ added later.  Feature testing is highly recommended. | ||||
| 
 | ||||
| :::info Inline Workers | ||||
| 
 | ||||
| Due to limitations of the live codeblocks, all of the workers in this section | ||||
| Due to limitations of the live code blocks, all of the workers in this section | ||||
| are in-line. The code is embedded in template literals. For production sites, | ||||
| typically workers are written in separate JS files. | ||||
| 
 | ||||
| @ -119,7 +172,31 @@ const worker = new Worker( | ||||
| ::: | ||||
| 
 | ||||
| Typically the Web Worker performs the `fetch` operation, processes the workbook, | ||||
| and sends a final result to the main browser context for processing. | ||||
| and sends a final result (HTML table or raw data) to the main browser context: | ||||
| 
 | ||||
| ```mermaid | ||||
| sequenceDiagram | ||||
|   autonumber | ||||
|   actor User | ||||
|   participant Page | ||||
|   participant Worker | ||||
|   User->>Page: click button | ||||
|   activate Page | ||||
|   Page->>Worker: send URL | ||||
|   deactivate Page | ||||
|   activate Worker | ||||
|   Note over Worker: fetch file | ||||
|   Note over Worker: parse file | ||||
|   Note over Worker: generate table | ||||
|   Worker->>Page: HTML table | ||||
|   deactivate Worker | ||||
|   activate Page | ||||
|   Note over Page: add to DOM | ||||
|   Page->>User: table is visible | ||||
|   deactivate Page | ||||
| ``` | ||||
| 
 | ||||
| <details><summary><b>Live Demo</b> (click to show)</summary> | ||||
| 
 | ||||
| In the following example, the script: | ||||
| 
 | ||||
| @ -172,6 +249,8 @@ self.addEventListener('message', async(e) => { | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| ## Creating a Local File | ||||
| 
 | ||||
| :::caution Writing files from Web Workers | ||||
| @ -181,8 +260,36 @@ the Web Worker to the main browser context for downloading. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| Typically the Web Worker receives an array of JS objects, generates a workbook, | ||||
| and sends a URL to the main browser context for download: | ||||
| 
 | ||||
| ```mermaid | ||||
| sequenceDiagram | ||||
|   autonumber | ||||
|   actor User | ||||
|   participant Page | ||||
|   participant Worker | ||||
|   User->>Page: click button | ||||
|   activate Page | ||||
|   Note over Page: collect dataset | ||||
|   Page->>Worker: transfer dataset | ||||
|   deactivate Page | ||||
|   activate Worker | ||||
|   Note over Worker: generate workbook | ||||
|   Note over Worker: create file | ||||
|   Note over Worker: setup download | ||||
|   Worker->>Page: URL to download | ||||
|   deactivate Worker | ||||
|   activate Page | ||||
|   Page->>User: download workbook | ||||
|   deactivate Page | ||||
| ``` | ||||
| 
 | ||||
| <details><summary><b>Live Demo</b> (click to show)</summary> | ||||
| 
 | ||||
| In the following example, the script: | ||||
| 
 | ||||
| - sends a dataset (array of JS objects) to the Web Worker | ||||
| - generates a workbook object in the Web Worker | ||||
| - generates a XLSB file using `XLSX.write` in the Web Worker | ||||
| - generates an object URL in the Web Worker | ||||
| @ -193,6 +300,11 @@ In the following example, the script: | ||||
| function SheetJSWriteFileWorker() { | ||||
|   const [__html, setHTML] = React.useState(""); | ||||
| 
 | ||||
|   const data = [ | ||||
|     { "SheetJS": "வணக்கம்", "in": "สวัสดี", "Web": "你好", "Workers": "가지마" }, | ||||
|     { "SheetJS": 1, "in": 2, "Web": 3, "Workers": 4 }, | ||||
|   ]; | ||||
| 
 | ||||
|   return ( <> | ||||
|     <button onClick={() => { setHTML(""); | ||||
|       /* this mantra embeds the worker source in the function */ | ||||
| @ -203,12 +315,10 @@ importScripts("https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js | ||||
| /* this callback will run once the main context sends a message */ | ||||
| self.addEventListener('message', async(e) => { | ||||
|   try { | ||||
|     /* Create a new Workbook (in this case, from a CSV string) */ | ||||
|     const csv = \`\ | ||||
| SheetJS,in,Web,Workers | ||||
| வணக்கம்,สวัสดี,你好,가지마 | ||||
| 1,2,3,4\`; | ||||
|     const wb = XLSX.read(csv, { type: "string", dense: true }); | ||||
|     /* Create a new workbook from the data */ | ||||
|     const ws = XLSX.utils.json_to_sheet(e.data.data); | ||||
|     const wb = XLSX.utils.book_new(); | ||||
|     XLSX.utils.book_append_sheet(wb, ws, "Data"); | ||||
| 
 | ||||
|     /* Write XLSB data (Uint8Array) */ | ||||
|     const u8 = XLSX.write(wb, { bookType: "xlsb", type: "buffer" }); | ||||
| @ -237,13 +347,15 @@ SheetJS,in,Web,Workers | ||||
|         document.body.removeChild(a); | ||||
|       }; | ||||
|       /* post a message to the worker */ | ||||
|       worker.postMessage({}); | ||||
|       worker.postMessage({ data }); | ||||
|     }}><b>Click to Start</b></button> | ||||
|     <div dangerouslySetInnerHTML={{ __html }}/> | ||||
|   </> ); | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| ## User-Submitted File | ||||
| 
 | ||||
| :::note FileReaderSync | ||||
| @ -253,6 +365,33 @@ synchronous version `FileReaderSync` is more efficient. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| Typically the Web Worker receives a file pointer, reads and parses the file, | ||||
| and sends a final result (HTML table or raw data) to the main browser context: | ||||
| 
 | ||||
| ```mermaid | ||||
| sequenceDiagram | ||||
|   autonumber | ||||
|   actor User | ||||
|   participant Page | ||||
|   participant Worker | ||||
|   User->>Page: click button | ||||
|   activate Page | ||||
|   Page->>Worker: send URL | ||||
|   deactivate Page | ||||
|   activate Worker | ||||
|   Note over Worker: fetch file | ||||
|   Note over Worker: parse file | ||||
|   Note over Worker: generate table | ||||
|   Worker->>Page: HTML table | ||||
|   deactivate Worker | ||||
|   activate Page | ||||
|   Note over Page: add to DOM | ||||
|   Page->>User: table is visible | ||||
|   deactivate Page | ||||
| ``` | ||||
| 
 | ||||
| <details><summary><b>Live Demo</b> (click to show)</summary> | ||||
| 
 | ||||
| In the following example, when a file is dropped over the DIV or when the INPUT | ||||
| element is used to select a file, the script: | ||||
| 
 | ||||
| @ -312,11 +451,15 @@ self.addEventListener('message', (e) => { | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| ## Streaming Write | ||||
| 
 | ||||
| A more general discussion, including row-oriented processing demos, is included | ||||
| in the ["Large Datasets"](/docs/demos/stream#browser) demo. | ||||
| 
 | ||||
| `XLSX.stream.to_csv` incrementally generates CSV rows. | ||||
| 
 | ||||
| #### File System Access API | ||||
| 
 | ||||
| :::warning Browser Compatibility | ||||
| @ -336,6 +479,41 @@ Strings larger than 500M may hit browser length limits. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| ```mermaid | ||||
| sequenceDiagram | ||||
|   autonumber | ||||
|   actor User | ||||
|   participant Page | ||||
|   participant Worker | ||||
|   User->>Page: click button | ||||
|   activate Page | ||||
|   Page->>User: seek permission | ||||
|   User->>Page: grant permission | ||||
|   Note over Page: collect dataset | ||||
|   Page->>Worker: transfer dataset | ||||
|   deactivate Page | ||||
|   activate Worker | ||||
|   Note over Worker: setup stream | ||||
|   Worker->>User: start download | ||||
|   loop every 100 rows | ||||
|     Note over Worker: generate rows | ||||
|     Worker->>User: write rows to file (without freezing) | ||||
|     Worker->>Page: progress message | ||||
|     activate Page | ||||
|     Page->>User: display progress | ||||
|     deactivate Page | ||||
|   end | ||||
|   Worker->>User: finish download | ||||
|   Worker->>Page: send competion message | ||||
|   deactivate Worker | ||||
|   activate Page | ||||
|   Page->>User: download complete | ||||
|   deactivate Page | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| <details><summary><b>Live Demo</b> (click to show)</summary> | ||||
| 
 | ||||
| The following live demo fetches and parses a file in a Web Worker.  The script: | ||||
| 
 | ||||
| - prompts user to save file (`window.showSaveFilePicker` in the main thread) | ||||
| @ -461,3 +639,5 @@ self.addEventListener('message', async(e) => { | ||||
|   </> ); | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
|  | ||||
| @ -316,4 +316,16 @@ function add_to_sheet(sheet, cell) { | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| </details> | ||||
| 
 | ||||
| #### Corrupt files | ||||
| 
 | ||||
| Third-party build tools and frameworks may post-process SheetJS scripts. The | ||||
| changes may result in corrupt files. | ||||
| 
 | ||||
| In the web browser, the standalone scripts from the SheetJS CDN will use proper | ||||
| encodings and should work in applications. The scripts typically can be added | ||||
| to an `index.html` file, bypassing any third-party post-processing | ||||
| 
 | ||||
| There are known bugs with the SWC minifier (used in Next.js 13+). The original | ||||
| minifier can be enabled by setting `swcMinify: false` in `next.config.js`. | ||||
|  | ||||
| @ -7,7 +7,7 @@ title: Overview | ||||
| # SheetJS CE | ||||
| 
 | ||||
|  | ||||
| [](https://github.com/SheetJS/sheetjs/actions) | ||||
| [](https://github.com/SheetJS/sheetjs/actions/workflows/node-4+.yml) | ||||
| [](https://snyk.io/test/github/SheetJS/sheetjs) | ||||
| [](https://cdn.sheetjs.com/) | ||||
| [](https://github.com/SheetJS/sheetjs) | ||||
|  | ||||
| @ -149,8 +149,12 @@ const config = { | ||||
|       } | ||||
|     }), | ||||
|   themes: [ | ||||
|     "@docusaurus/theme-live-codeblock" | ||||
|     "@docusaurus/theme-live-codeblock", | ||||
|     "@docusaurus/theme-mermaid" | ||||
|   ], | ||||
|   markdown: { | ||||
|     mermaid: true | ||||
|   }, | ||||
|   scripts: [ | ||||
|     { | ||||
|       src: "https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js", | ||||
|  | ||||
| @ -20,6 +20,7 @@ | ||||
|     "@docusaurus/preset-classic": "2.2.0", | ||||
|     "@docusaurus/theme-common": "2.2.0", | ||||
|     "@docusaurus/theme-live-codeblock": "2.2.0", | ||||
|     "@docusaurus/theme-mermaid": "2.2.0", | ||||
|     "@mdx-js/react": "1.6.22", | ||||
|     "clsx": "1.2.1", | ||||
|     "prism-react-renderer": "1.3.5", | ||||
|  | ||||
| @ -16,7 +16,7 @@ export default function Index({type, snames}) { return ( <div> | ||||
|     Each worksheet maps to a path:<br/><br/> | ||||
|     <ul> | ||||
| {snames.map((sname, idx) => (<li key={idx}> | ||||
|   <Link href="/sheets/[id]" as={`/sheets/${idx}`}><a>{`Sheet index=${idx} name="${sname}"`}</a></Link> | ||||
|   <Link href="/sheets/[id]" as={`/sheets/${idx}`}>{`Sheet index=${idx} name="${sname}"`}</Link> | ||||
| </li>))} | ||||
|     </ul> | ||||
|   </pre> | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user