| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | --- | 
					
						
							|  |  |  | title: NextJS | 
					
						
							| 
									
										
										
										
											2023-02-28 11:40:44 +00:00
										 |  |  | pagination_prev: demos/net/index | 
					
						
							|  |  |  | pagination_next: demos/mobile/index | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | --- | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-27 09:12:19 +00:00
										 |  |  | import current from '/version.js'; | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | import Tabs from '@theme/Tabs'; | 
					
						
							|  |  |  | import TabItem from '@theme/TabItem'; | 
					
						
							| 
									
										
										
										
											2023-04-29 11:21:37 +00:00
										 |  |  | import CodeBlock from '@theme/CodeBlock'; | 
					
						
							| 
									
										
										
										
											2023-04-27 09:12:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-02 02:17:56 +00:00
										 |  |  | NextJS is a server-side framework for building static and dynamic sites. For | 
					
						
							|  |  |  | pure static sites, [Webpack loaders](/docs/demos/static/webpack) can preprocess | 
					
						
							|  |  |  | files and NextJS can build static pages from spreadsheets. For dynamic sites, | 
					
						
							|  |  |  | NextJS lifecycle methods can read files on the server side. | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | The [NodeJS module](/docs/getting-started/installation/nodejs) can be imported | 
					
						
							|  |  |  | from pages or loaded in Webpack loaders. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::warning | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | [`import`](/docs/getting-started/installation/nodejs#esm-import) does not load | 
					
						
							|  |  |  | NodeJS native modules. The Installation section includes a note on dynamic | 
					
						
							|  |  |  | import of `fs` within lifecycle methods. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NextJS best practices have evolved over time, but there are three key parts: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 1) [Loading Data](#loading-data): NextJS can read files in lifecycle methods OR | 
					
						
							|  |  |  | custom Webpack loaders can create asset modules. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 2) [Lifecycle Methods](#nextjs-strategies): NextJS includes strategies for | 
					
						
							|  |  |  | static pages (`getStaticProps`) as well as dynamic pages (`getServerSideProps`). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 3) [Data Presentation](#data-presentation): Pages use React and JSX. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::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 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-02 02:17:56 +00:00
										 |  |  | :::warning Telemetry | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NextJS collects telemetry by default. The `telemetry` subcommand can disable it: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | npx next@13.4.4 telemetry disable | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The setting can be verified by running | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | npx next@13.4.4 telemetry status | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::note | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The following deployments were tested: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | NextJS | Date       | | 
					
						
							|  |  |  | |:-------|:-----------| | 
					
						
							|  |  |  | | 13.1.1 | 2023-01-14 | | 
					
						
							|  |  |  | | 13.4.4 | 2023-05-26 | | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | ## Loading Data
 | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | At a high level, there are two ways to pull spreadsheet data into NextJS apps: | 
					
						
							|  |  |  | loading an asset module or performing the file read operations from the NextJS | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | lifecycle methods. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Asset modules are appropriate for static sites when the file names are known in | 
					
						
							|  |  |  | advance. Performing file read operations in lifecycle methods is more flexible | 
					
						
							|  |  |  | but does not support live reloading. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Asset Module
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::caution | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | When the demo was last tested, Turbopack did not support true raw loaders. For | 
					
						
							|  |  |  | development use, the normal `npx next dev` should be used. | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | The following diagram depicts the workbook waltz: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```mermaid | 
					
						
							|  |  |  | flowchart LR | 
					
						
							|  |  |  |   file[(workbook\nfile)] | 
					
						
							|  |  |  |   subgraph SheetJS operations | 
					
						
							|  |  |  |     base64(base64\nstring) | 
					
						
							|  |  |  |     aoo(array of\nobjects) | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  |   html{{HTML\nTABLE}} | 
					
						
							|  |  |  |   file --> |base64-loader.js\ncustom plugin| base64 | 
					
						
							|  |  |  |   base64 --> |page\nlifecycle method| aoo | 
					
						
							|  |  |  |   aoo --> |page\nIndex method| html | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | In this flow, it is strongly recommended to make a loader return a Base64 string: | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | ```js title="base64-loader.js" | 
					
						
							|  |  |  | function loader(content) { | 
					
						
							|  |  |  |   /* since `loader.raw` is true, `content` is a Buffer */ | 
					
						
							|  |  |  |   return `export default '${content.toString("base64")}'`; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | /* ensure the function receives a Buffer */ | 
					
						
							|  |  |  | loader.raw = true; | 
					
						
							|  |  |  | module.exports = loader; | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The webpack configuration is controlled in `next.config.js`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js title="next.config.js" | 
					
						
							|  |  |  | module.exports = { | 
					
						
							|  |  |  |   webpack: (config) => { | 
					
						
							|  |  |  |     // highlight-start | 
					
						
							|  |  |  |     /* add to the webpack config module.rules array */ | 
					
						
							|  |  |  |     config.module.rules.push({ | 
					
						
							|  |  |  |       /* `test` matches file extensions */ | 
					
						
							|  |  |  |       test: /\.(numbers|xls|xlsx|xlsb)/, | 
					
						
							|  |  |  |       /* use the loader script */ | 
					
						
							|  |  |  |       use: [ { loader: './base64-loader' } ] | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     // highlight-end | 
					
						
							|  |  |  |     return config; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Module alias directories can be defined in `jsconfig.json` or `tsconfig.json`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```json title="jsconfig.json" | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   "compilerOptions": { | 
					
						
							|  |  |  |     "baseUrl": ".", | 
					
						
							|  |  |  |     "paths": { | 
					
						
							|  |  |  |       // highlight-next-line | 
					
						
							|  |  |  |       "@/*": ["*"] | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Pages can import the files directly. It is strongly recommended to store files | 
					
						
							|  |  |  | in a `data` folder. This example uses `getStaticProps` to parse `sheetjs.xlsx`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```jsx title="index.js" | 
					
						
							|  |  |  | import { read, utils } from 'xlsx'; | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | // highlight-next-line | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | import base64 from '@/data/sheetjs.xlsx'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export async function getStaticProps() { | 
					
						
							|  |  |  |   /* parse base64 data */ | 
					
						
							|  |  |  |   // highlight-next-line | 
					
						
							|  |  |  |   const wb = read(base64, { type: "base64" }); | 
					
						
							|  |  |  |   return { props: { | 
					
						
							|  |  |  |       /* generate array of objects from the first sheet */ | 
					
						
							|  |  |  |       data: utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]) | 
					
						
							|  |  |  |   } }; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | ### Raw Operations
 | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | Files can be read using `readFile` in lifecycle methods. The `cwd` method from | 
					
						
							|  |  |  | the `process` module will point to the root of the project. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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 --> |page\nlifecycle method| buffer | 
					
						
							|  |  |  |   buffer --> |page\nlifecycle method| aoo | 
					
						
							|  |  |  |   aoo --> |page\nIndex method| html | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This example reads the file `sheetjs.xlsx` in the `data` folder in the project: | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | import { readFile, utils, set_fs } from 'xlsx'; | 
					
						
							|  |  |  | import { join } from 'path'; | 
					
						
							|  |  |  | import { cwd } from 'process'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export async function getServerSideProps() { | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | // highlight-start | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  |   set_fs(await import("fs")); // dynamically import 'fs' when needed | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  |   const filename = join(cwd(), "data", "sheetjs.xlsx"); // /data/sheetjs.xlsx | 
					
						
							|  |  |  |   const wb = readFile(filename); | 
					
						
							|  |  |  |   // highlight-end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* generate and return the html from the first worksheet */ | 
					
						
							|  |  |  |   const data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]); | 
					
						
							|  |  |  |   return { props: { data } }; | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | :::warning Reading and writing files during the build process | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | As the NextJS workaround is non-traditional, it bears repeating: | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | `fs` cannot be statically imported from the top level in NextJS pages.  The | 
					
						
							|  |  |  | dynamic import must happen within a lifecycle function. | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | ## NextJS Strategies
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NextJS currently provides 3 strategies: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - "Static Site Generation" using `getStaticProps` | 
					
						
							|  |  |  | - "SSG with Dynamic Routes" using `getStaticPaths` | 
					
						
							|  |  |  | - "Server-Side Rendering" using `getServerSideProps` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Static Site Generation
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | When using `getStaticProps`, the file will be read once during build time. | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | This example reads `sheetjs.xlsx` from the `data` folder: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <Tabs groupId="data"> | 
					
						
							|  |  |  |   <TabItem value="asset" label="Asset Module"> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | import { read, utils } from 'xlsx'; | 
					
						
							|  |  |  | import base64 from '@/data/sheetjs.xlsx'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export async function getStaticProps() { | 
					
						
							|  |  |  |   const wb = read(base64, { type: "base64" }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* generate and return the html from the first worksheet */ | 
					
						
							|  |  |  |   const html = utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]); | 
					
						
							|  |  |  |   return { props: { html } }; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   </TabItem> | 
					
						
							|  |  |  |   <TabItem value="raw" label="Raw Operations"> | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | import { readFile, set_fs, utils } from 'xlsx'; | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | import { join } from 'path'; | 
					
						
							|  |  |  | import { cwd } from 'process'; | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | export async function getStaticProps() { | 
					
						
							|  |  |  |   set_fs(await import("fs")); | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  |   const filename = join(cwd(), "data", "sheetjs.xlsx"); // /data/sheetjs.xlsx | 
					
						
							|  |  |  |   const wb = readFile(filename); | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* generate and return the html from the first worksheet */ | 
					
						
							|  |  |  |   const html = utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]); | 
					
						
							|  |  |  |   return { props: { html } }; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  |   </TabItem> | 
					
						
							|  |  |  | </Tabs> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | ### Dynamic Routes
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Typically a static site with dynamic routes has an endpoint `/sheets/[id]` that | 
					
						
							|  |  |  | implements both `getStaticPaths` and `getStaticProps`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - `getStaticPaths` should return an array of worksheet indices: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | <Tabs groupId="data"> | 
					
						
							|  |  |  |   <TabItem value="asset" label="Asset Module"> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | ```js | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | import { read } from 'xlsx'; | 
					
						
							|  |  |  | import base64 from '@/data/sheetjs.xlsx'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export async function getStaticPaths() { | 
					
						
							|  |  |  |   /* read file */ | 
					
						
							|  |  |  |   const wb = read(base64, { type: "base64" }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* generate an array of objects that will be used for generating pages */ | 
					
						
							|  |  |  |   const paths = wb.SheetNames.map((name, idx) => ({ params: { id: idx.toString() } })); | 
					
						
							|  |  |  |   return { paths, fallback: false }; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   </TabItem> | 
					
						
							|  |  |  |   <TabItem value="raw" label="Raw Operations"> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | import { readFile, set_fs } from 'xlsx'; | 
					
						
							|  |  |  | import { join } from 'path'; | 
					
						
							|  |  |  | import { cwd } from 'process'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | export async function getStaticPaths() { | 
					
						
							|  |  |  |   /* read file */ | 
					
						
							|  |  |  |   set_fs(await import("fs")); | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  |   const filename = join(cwd(), "data", "sheetjs.xlsx"); // /data/sheetjs.xlsx | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  |   const wb = readFile(path); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* generate an array of objects that will be used for generating pages */ | 
					
						
							|  |  |  |   const paths = wb.SheetNames.map((name, idx) => ({ params: { id: idx.toString() } })); | 
					
						
							|  |  |  |   return { paths, fallback: false }; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  |   </TabItem> | 
					
						
							|  |  |  | </Tabs> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | :::note | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | For a pure static site, `fallback` must be set to `false`! | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - `getStaticProps` will generate the actual HTML for each page: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | <Tabs groupId="data"> | 
					
						
							|  |  |  |   <TabItem value="asset" label="Asset Module"> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | ```js | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | import { read, utils } from 'xlsx'; | 
					
						
							|  |  |  | import base64 from '@/data/sheetjs.xlsx'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export async function getStaticProps(ctx) { | 
					
						
							|  |  |  |   /* read file */ | 
					
						
							|  |  |  |   const wb = read(base64, { type: "base64" }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* get the corresponding worksheet and generate HTML */ | 
					
						
							|  |  |  |   const ws = wb.Sheets[wb.SheetNames[ctx.params.id]]; // id from getStaticPaths | 
					
						
							|  |  |  |   const html = utils.sheet_to_html(ws); | 
					
						
							|  |  |  |   return { props: { html } }; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   </TabItem> | 
					
						
							|  |  |  |   <TabItem value="raw" label="Raw Operations"> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | import { readFile, set_fs, utils } from 'xlsx'; | 
					
						
							|  |  |  | import { join } from 'path'; | 
					
						
							|  |  |  | import { cwd } from 'process'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | export async function getStaticProps(ctx) { | 
					
						
							|  |  |  |   /* read file */ | 
					
						
							|  |  |  |   set_fs(await import("fs")); | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  |   const filename = join(cwd(), "data", "sheetjs.xlsx"); // /data/sheetjs.xlsx | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  |   const wb = readFile(path); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* get the corresponding worksheet and generate HTML */ | 
					
						
							|  |  |  |   const ws = wb.Sheets[wb.SheetNames[ctx.params.id]]; // id from getStaticPaths | 
					
						
							|  |  |  |   const html = utils.sheet_to_html(ws); | 
					
						
							|  |  |  |   return { props: { html } }; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  |   </TabItem> | 
					
						
							|  |  |  | </Tabs> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | ### Server-Side Rendering
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::caution Do not use on a static site | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | These routes require a NodeJS dynamic server. Static page generation will fail! | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `getStaticProps` and `getStaticPaths` support static site generation (SSG). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `getServerSideProps` is suited for NodeJS hosted deployments where the workbook | 
					
						
							|  |  |  | changes frequently and a static site is undesirable. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | When using `getServerSideProps`, the file will be read on each request. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | <Tabs groupId="data"> | 
					
						
							|  |  |  |   <TabItem value="asset" label="Asset Module"> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::caution Consider using a static strategy | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | When using asset modules, the file names and file paths are processed during the | 
					
						
							|  |  |  | build step. The content is fixed. In this situation, a static approach such as | 
					
						
							|  |  |  | `getStaticProps` is strongly recommended. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | import { read } from 'xlsx'; | 
					
						
							|  |  |  | import base64 from '@/data/sheetjs.xlsx'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export async function getServerSideProps() { | 
					
						
							|  |  |  |   /* read file */ | 
					
						
							|  |  |  |   const wb = read(base64, { type: "base64" }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* generate and return the html from the first worksheet */ | 
					
						
							|  |  |  |   const html = utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]); | 
					
						
							|  |  |  |   return { props: { html } }; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   </TabItem> | 
					
						
							|  |  |  |   <TabItem value="raw" label="Raw Operations"> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | ```js | 
					
						
							|  |  |  | import { readFile, set_fs, utils } from 'xlsx'; | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | import { join } from 'path'; | 
					
						
							|  |  |  | import { cwd } from 'process'; | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | export async function getServerSideProps() { | 
					
						
							|  |  |  |   /* read file */ | 
					
						
							|  |  |  |   set_fs(await import("fs")); | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  |   const filename = join(cwd(), "data", "sheetjs.xlsx"); // /data/sheetjs.xlsx | 
					
						
							|  |  |  |   const wb = readFile(path); | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* generate and return the html from the first worksheet */ | 
					
						
							|  |  |  |   const html = utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]); | 
					
						
							|  |  |  |   return { props: { html } }; | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   </TabItem> | 
					
						
							|  |  |  | </Tabs> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Data Presentation
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | [The React demo](/docs/demos/frontend/react) compares common approaches. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### HTML
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | HTML output can be generated using `XLSX.utils.sheet_to_html` and inserted into | 
					
						
							|  |  |  | the document using the `dangerouslySetInnerHTML` attribute: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```mermaid | 
					
						
							|  |  |  | flowchart LR | 
					
						
							|  |  |  |   subgraph SheetJS operations | 
					
						
							|  |  |  |     data(File\nData) | 
					
						
							|  |  |  |     code{{HTML\nTABLE}} | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  |   html{{Rendered\nPage}} | 
					
						
							|  |  |  |   data --> |lifecycle\nsheet_to_html| code | 
					
						
							|  |  |  |   code --> |Index\ninnerHTML| html | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```jsx | 
					
						
							|  |  |  | export default function Index({html, type}) { return ( | 
					
						
							|  |  |  |   <div dangerouslySetInnerHTML={{ __html: html }} /> | 
					
						
							|  |  |  | ); } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Arrays of Objects
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Arrays of objects can be generated using `XLSX.utils.sheet_to_json` and inserted | 
					
						
							|  |  |  | into the document using standard JSX: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```mermaid | 
					
						
							|  |  |  | flowchart LR | 
					
						
							|  |  |  |   subgraph SheetJS operations | 
					
						
							|  |  |  |     data(File\nData) | 
					
						
							|  |  |  |     aoo(array of\nobjects) | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  |   html{{Rendered\nPage}} | 
					
						
							|  |  |  |   data --> |lifecycle\nsheet_to_json| aoo | 
					
						
							|  |  |  |   aoo --> |Index\nReact + JSX| html | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```jsx | 
					
						
							|  |  |  | export default function Index({aoo, type}) { return ( | 
					
						
							|  |  |  |   <table><thead><tr key={0}><th>Name</th><th>Index</th></tr></thead><tbody> | 
					
						
							|  |  |  | // highlight-start | 
					
						
							|  |  |  |     {aoo.map(row => ( <tr> | 
					
						
							|  |  |  |       <td>{row.Name}</td> | 
					
						
							|  |  |  |       <td>{row.Index}</td> | 
					
						
							|  |  |  |     </tr>))} | 
					
						
							|  |  |  | // highlight-end | 
					
						
							|  |  |  |   </tbody></table> | 
					
						
							|  |  |  | ); } | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Demo
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | :::note | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This demo showcases the following SheetJS + NextJS flows: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | Page                  | Loading Data | Lifecycle Method     | SheetJS API     | | 
					
						
							|  |  |  | |:----------------------|:-------------|:---------------------|:----------------| | 
					
						
							|  |  |  | | `/getStaticProps`     | asset module | `getStaticProps`     | `sheet_to_json` | | 
					
						
							|  |  |  | | `/sheets/[id]`        | asset module | `getStaticPaths`     | `sheet_to_html` | | 
					
						
							|  |  |  | | `/getServerSideProps` | lifecycle    | `getServerSideProps` | `sheet_to_html` | | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Initial Setup
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 0) Disable NextJS telemetry: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | npx next@13.4.4 telemetry disable | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Confirm it is disabled by running | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | npx next@13.4.4 telemetry status | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 1) Set up folder structure.  At the end, a `pages` folder with a `sheets` | 
					
						
							|  |  |  |    subfolder must be created.  On Linux or MacOS or WSL: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | mkdir sheetjs-next | 
					
						
							|  |  |  | cd sheetjs-next | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | mkdir -p pages/sheets/ | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 2) Download the [test file](pathname:///next/sheetjs.xlsx) and place in the | 
					
						
							|  |  |  |    project root.  On Linux or MacOS or WSL: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | curl -LO https://docs.sheetjs.com/next/sheetjs.xlsx | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 3) Install dependencies: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-29 11:21:37 +00:00
										 |  |  | <CodeBlock language="bash">{`\ | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz next@13.4.4`} | 
					
						
							| 
									
										
										
										
											2023-04-29 11:21:37 +00:00
										 |  |  | </CodeBlock> | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | 4) Download NextJS config scripts and place in the root folder: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - [`base64-loader.js`](pathname:///next/base64-loader.js) | 
					
						
							|  |  |  | - [`jsconfig.json`](pathname:///next/jsconfig.json) | 
					
						
							|  |  |  | - [`next.config.js`](pathname:///next/next.config.js) | 
					
						
							|  |  |  | - [`styles.css`](pathname:///next/styles.css) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | On Linux or MacOS or WSL: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | curl -LO https://docs.sheetjs.com/next/base64-loader.js | 
					
						
							|  |  |  | curl -LO https://docs.sheetjs.com/next/jsconfig.json | 
					
						
							|  |  |  | curl -LO https://docs.sheetjs.com/next/next.config.js | 
					
						
							|  |  |  | curl -LO https://docs.sheetjs.com/next/styles.css | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 5) Download test scripts: | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Download and place the following scripts in the `pages` subfolder: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | - [`_app.js`](pathname:///next/_app.js) | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | - [`index.js`](pathname:///next/index.js) | 
					
						
							|  |  |  | - [`getServerSideProps.js`](pathname:///next/getServerSideProps.js) | 
					
						
							|  |  |  | - [`getStaticPaths.js`](pathname:///next/getStaticPaths.js) | 
					
						
							|  |  |  | - [`getStaticProps.js`](pathname:///next/getStaticProps.js) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Download [`[id].js`](pathname:///next/%5Bid%5D.js) and place in the | 
					
						
							|  |  |  | `pages/sheets` subfolder. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::caution Percent-Encoding in the script name | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The `[id].js` script must have the literal square brackets in the name. If your | 
					
						
							|  |  |  | browser saved the file to `%5Bid%5D.js`. rename the file. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | On Linux or MacOS or WSL: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | cd pages | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | curl -LO https://docs.sheetjs.com/next/_app.js | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | curl -LO https://docs.sheetjs.com/next/index.js | 
					
						
							|  |  |  | curl -LO https://docs.sheetjs.com/next/getServerSideProps.js | 
					
						
							|  |  |  | curl -LO https://docs.sheetjs.com/next/getStaticPaths.js | 
					
						
							|  |  |  | curl -LO https://docs.sheetjs.com/next/getStaticProps.js | 
					
						
							|  |  |  | cd sheets | 
					
						
							|  |  |  | curl -LOg 'https://docs.sheetjs.com/next/[id].js' | 
					
						
							|  |  |  | cd ../.. | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | ### Testing
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 6) Test the deployment: | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | npx next@13.4.4 | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Open a web browser and access: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-03 03:40:40 +00:00
										 |  |  | - `http://localhost:3000` landing page | 
					
						
							|  |  |  | - `http://localhost:3000/getStaticProps` shows data from the first sheet | 
					
						
							|  |  |  | - `http://localhost:3000/getServerSideProps` shows data from the first sheet | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | - `http://localhost:3000/getStaticPaths` shows a list (2 sheets) | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | The individual worksheets are available at | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-03 03:40:40 +00:00
										 |  |  | - `http://localhost:3000/sheets/0` | 
					
						
							|  |  |  | - `http://localhost:3000/sheets/1` | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | 7) While the development server is running, open the `/getStaticProps` page and | 
					
						
							|  |  |  | open `sheetjs.xlsx` with a spreadsheet editor. In the editor, add a row to the | 
					
						
							|  |  |  | bottom of the "Indices" worksheet. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | After saving the file, the website should refresh with the new row. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Production Build
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 8) Stop the server and run a production build: | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | npx next@13.4.4 build | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The final output will show a list of the routes and types: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | Route (pages)                              Size     First Load JS | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | ┌ ○ /                                      563 B          74.4 kB | 
					
						
							|  |  |  | ├   /_app                                  0 B            73.9 kB | 
					
						
							|  |  |  | ├ ○ /404                                   182 B          74.1 kB | 
					
						
							|  |  |  | ├ λ /getServerSideProps                    522 B          74.4 kB | 
					
						
							|  |  |  | ├ ● /getStaticPaths                        2.89 kB        76.8 kB | 
					
						
							|  |  |  | ├ ● /getStaticProps                        586 B          74.5 kB | 
					
						
							|  |  |  | └ ● /sheets/[id]                           522 B          74.4 kB | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  |     ├ /sheets/0 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  |     └ /sheets/1 | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | As explained in the summary, the `/getStaticPaths` and `/getStaticProps` routes | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | are completely static.  2 `/sheets/#` pages were generated, corresponding to 2 | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | worksheets in the file.  `/getServerSideProps` is server-rendered. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | 9) Try to build a static site: | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | npx next@13.4.4 export | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::note The static export will fail! | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | A static page cannot be generated at this point because `/getServerSideProps` | 
					
						
							|  |  |  | is still server-rendered. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | ### Static Site
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 10) Delete `pages/getServerSideProps.js` and rebuild: | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | rm -f pages/getServerSideProps.js | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | npx next@13.4.4 build | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Inspecting the output, there should be no lines with the `λ` symbol: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | Route (pages)                              Size     First Load JS | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | ┌ ○ /                                      563 B          74.4 kB | 
					
						
							|  |  |  | ├   /_app                                  0 B            73.9 kB | 
					
						
							|  |  |  | ├ ○ /404                                   182 B          74.1 kB | 
					
						
							|  |  |  | ├ ● /getStaticPaths                        2.89 kB        76.8 kB | 
					
						
							|  |  |  | ├ ● /getStaticProps                        586 B          74.5 kB | 
					
						
							|  |  |  | └ ● /sheets/[id]                           522 B          74.4 kB | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  |     ├ /sheets/0 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  |     └ /sheets/1 | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | 11) Generate the static site: | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | npx next@13.4.4 export | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 22:50:23 +00:00
										 |  |  | The static site will be written to the `out` subfolder | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 12) Serve the static site: | 
					
						
							| 
									
										
										
										
											2023-01-15 03:36:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npx http-server out | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The command will start a local HTTP server for testing the generated site. Note | 
					
						
							|  |  |  | that `/getServerSideProps` will 404 since the page was removed. |