Next.js & Nextra static export example
Tags: nextra, nextjs, typescript, azurepipelines
Published: 2023-03-03 12:48:46

In this short post I will show you how to static export your [Nextra](https://nextra.site/) blog or documentation using [Azure Pipelines](https://azure.microsoft.com/de-de/products/devops/pipelines).

## Introduction
To make a static export from a Next.js or a Nextra application you have to consider a few things.

The following functions of Next.js are no longer supported in a static export:

- [Image Optimization](https://nextjs.org/docs/basic-features/image-optimization) (default loader)
- [Internationalized Routing](https://nextjs.org/docs/advanced-features/i18n-routing)
- [API Routes](https://nextjs.org/docs/api-routes/introduction)
- [Rewrites](https://nextjs.org/docs/api-reference/next.config.js/rewrites)
- [Redirects](https://nextjs.org/docs/api-reference/next.config.js/redirects)
- [Headers](https://nextjs.org/docs/api-reference/next.config.js/headers)
- [Middleware](https://nextjs.org/docs/middleware)
- [Incremental Static Regeneration](https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration)
- `fallback: true`
- `getServerSideProps`

More information about Static HTML Export can be found [here](https://nextjs.org/docs/advanced-features/static-html-export).

In order to continue using the image component in our code, a few adjustments are necessary. I will show you in this article how you can use the static export without problems.

## Create a custom Image component
To get started we will create a new component called Image in the folder components/ with the following lines of code.

```typescript
interface ImageProps {
    alt?: string
    src: string
}

const Image: React.FC<ImageProps> = ({
    children,
    alt = 'Image Alt',
    src
}) => {
    return (
        <img alt={alt} src={(process.env.NEXT_PUBLIC_BASE_PATH || '') + src} />
    )
}

export default Image
```
The component accepts two variables called alt and src. Just like in the Next.js image component, the alt tag and the image source can be defined here. In addition, an environment variable NEXT_PUBLIC_BASE_PATH is used to define the base path of your application. This is necessary to avoid errors when loading images with a static export.

## Nextra Configuration
In addition to the custom image component, we also need to make the following changes in the next.config.js file.

1. Set `unstable_staticImage` to `false`
2. Set `trailingSlash` to `true`
3. Set the `basePath` to the `NEXT_PUBLIC_BASE_PATH` environment variable

With these settings the loading of images and dynamic links is also possible within the static export.

```typescript
const withNextra = require('nextra')({
  //Nextra
  theme: 'nextra-theme-docs',
  themeConfig: './theme.config.js',
  unstable_staticImage: false
});
const path = require('path');

module.exports = withNextra({
  sassOptions: {
    includePaths: [path.join(__dirname, 'styles')],
  },
  trailingSlash: true,
  basePath: process.env.NEXT_PUBLIC_BASE_PATH || ''
});
```

## Azure Pipeline Setup
Optionally, an Azure pipeline can be set up to automatically perform a build and static export when changes are checked into your Git repository.

This pipeline includes:

- npm package Caching
- npm build of the Nextra application
- The static export of your Nextra application
- Publish of a build artifact including your static export

```yaml
stages:
- stage: Build
  pool:
    vmImage: ubuntu-latest
    demands:
      - npm
  jobs:
  - job: BuildProject
    displayName: Build Project
    variables:
      npm_config_cache: $(Pipeline.Workspace)/.npm
      basePath: '/'
    steps:
    - task: Cache@2
      inputs:
        key: 'npm | "$(Agent.OS)" | package-lock.json'
        restoreKeys: |
          npm | "$(Agent.OS)"
        path: $(npm_config_cache)
      displayName: Cache npm
    - task: NodeTool@0
      inputs:
        versionSpec: '14.x'
    - task: Npm@1
      displayName: 'npm install'
      inputs:
        command: 'ci'
    - task: Npm@1
      displayName: 'npm build'
      env:
        NEXT_PUBLIC_BASE_PATH: $(basePath)
      inputs:
        command: 'custom'
        customCommand: 'run build'
    - task: Npm@1
      inputs:
        command: 'custom'
        customCommand: 'run export'
    - task: PublishBuildArtifacts@1
      inputs:
        PathtoPublish: 'out'
```

## Links
[Gist](https://gist.github.com/sebiweise/81fac68c851de1992460d3f995c9804a)
[Azure DevOps](https://azure.microsoft.com/de-de/products/devops)
[Nextra](https://nextra.site/)