Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide custom 404 static pages #412

Closed
2 tasks
zawasp opened this issue May 22, 2023 · 6 comments
Closed
2 tasks

Provide custom 404 static pages #412

zawasp opened this issue May 22, 2023 · 6 comments
Labels
enhancement New feature or request

Comments

@zawasp
Copy link
Contributor

zawasp commented May 22, 2023

Which scope/s are relevant/related to the feature request?

Don't known / other

Information

It would be useful to be able to pre-render custom 404.html pages from Angular pages, similar to: https://docs.astro.build/en/core-concepts/astro-pages/#custom-404-error-page

Ideally, multiple custom 404.html pages could be created, one per route. This would help deploying static sites to Cloudflare Pages

Describe any alternatives/workarounds you're currently using

No response

I would be willing to submit a PR to fix this issue

  • Yes
  • No
@zawasp zawasp added the enhancement New feature or request label May 22, 2023
@brandonroberts
Copy link
Member

This can be done by prerendering an API route, similar to rendering an XML feed

https://analogjs.org/docs/features/api/overview#defining-xml-content

@anuj9196
Copy link

anuj9196 commented Aug 8, 2024

@brandonroberts
I'm getting this error

ERROR RuntimeError: NG04002: '404.html'
    at Recognizer.noMatchError (file:///.../dist/ssr/main.server.js:45909:12)
    at file:///.../dist/ssr/main.server.js:45943:20
    at /.../node_modules/rxjs/dist/cjs/internal/operators/catchError.js:13:51
    at OperatorSubscriber._this._error (/.../node_modules/rxjs/dist/cjs/internal/operators/OperatorSubscriber.js:43:21)
    at Subscriber.error (/.../node_modules/rxjs/dist/cjs/internal/Subscriber.js:60:18)
    at Subscriber._error (/.../node_modules/rxjs/dist/cjs/internal/Subscriber.js:84:30)
    at Subscriber.error (/.../node_modules/rxjs/dist/cjs/internal/Subscriber.js:60:18)
    at Subscriber._error (/.../node_modules/rxjs/dist/cjs/internal/Subscriber.js:84:30)
    at Subscriber.error (/.../node_modules/rxjs/dist/cjs/internal/Subscriber.js:60:18)
    at Subscriber._error (/.../node_modules/rxjs/dist/cjs/internal/Subscriber.js:84:30)
    at Subscriber.error (/Us.../node_modules/rxjs/dist/cjs/internal/Subscriber.js:60:18)
    at Subscriber._error (/.../node_modules/rxjs/dist/cjs/internal/Subscriber.js:84:30)
    at Subscriber.error (/.../node_modules/rxjs/dist/cjs/internal/Subscriber.js:60:18)
    at Subscriber._error (/.../node_modules/rxjs/dist/cjs/internal/Subscriber.js:84:30)
    at Subscriber.error (/.../node_modules/rxjs/dist/cjs/internal/Subscriber.js:60:18)
    at Subscriber._error (/.../node_modules/rxjs/dist/cjs/internal/Subscriber.js:84:30)
    at Subscriber.error (/.../node_modules/rxjs/dist/cjs/internal/Subscriber.js:60:18)
    at Subscriber._error (/.../node_modules/rxjs/dist/cjs/internal/Subscriber.js:84:30)
    at Subscriber.error (/.../node_modules/rxjs/dist/cjs/internal/Subscriber.js:60:18)
    at Subscriber._error (/.../node_modules/rxjs/dist/cjs/internal/Subscriber.js:84:30)
    at Subscriber.error (/.../node_modules/rxjs/dist/cjs/internal/Subscriber.js:60:18)
    at Observable.init [as _subscribe] (/.../node_modules/rxjs/dist/cjs/internal/observable/throwError.js:8:58)
    at Observable._trySubscribe (/.../node_modules/rxjs/dist/cjs/internal/Observable.js:41:25)
    at /.../node_modules/rxjs/dist/cjs/internal/Observable.js:35:31
    at Object.errorContext (/.../node_modules/rxjs/dist/cjs/internal/util/errorContext.js:22:9)
    at Observable.subscribe (/.../node_modules/rxjs/dist/cjs/internal/Observable.js:26:24)
    at /.../node_modules/rxjs/dist/cjs/internal/operators/catchError.js:17:31
    at OperatorSubscriber._this._error (/.../node_modules/rxjs/dist/cjs/internal/operators/OperatorSubscriber.js:43:21)
    at Subscriber.error (/.../node_modules/rxjs/dist/cjs/internal/Subscriber.js:60:18)
    at /.../node_modules/rxjs/dist/cjs/internal/operators/throwIfEmpty.js:14:80
    at OperatorSubscriber._this._complete (/.../node_modules/rxjs/dist/cjs/internal/operators/OperatorSubscriber.js:56:21)
    at Subscriber.complete (/.../node_modules/rxjs/dist/cjs/internal/Subscriber.js:69:18)
    at Subscriber._complete (/.../node_modules/rxjs/dist/cjs/internal/Subscriber.js:92:30)
    at Subscriber.complete (/.../node_modules/rxjs/dist/cjs/internal/Subscriber.js:69:18)
    at Subscriber._complete (/.../node_modules/rxjs/dist/cjs/internal/Subscriber.js:92:30)
    at Subscriber.complete (/.../node_modules/rxjs/dist/cjs/internal/Subscriber.js:69:18)
    at checkComplete (/.../node_modules/rxjs/dist/cjs/internal/operators/mergeInternals.js:14:24)
    at OperatorSubscriber.onFinalize (/.../node_modules/rxjs/dist/cjs/internal/operators/mergeInternals.js:48:21)
    at OperatorSubscriber.unsubscribe (/.../node_modules/rxjs/dist/cjs/internal/operators/OperatorSubscriber.js:73:90)
    at OperatorSubscriber._this._complete (/.../node_modules/rxjs/dist/cjs/internal/operators/OperatorSubscriber.js:62:26)
    at Subscriber.complete (/.../node_modules/rxjs/dist/cjs/internal/Subscriber.js:69:18)
    at Observable._subscribe (/.../node_modules/rxjs/dist/cjs/internal/observable/innerFrom.js:111:20)
    at Observable._trySubscribe (/.../node_modules/rxjs/dist/cjs/internal/Observable.js:41:25)
    at /.../node_modules/rxjs/dist/cjs/internal/Observable.js:35:31
    at Object.errorContext (/.../node_modules/rxjs/dist/cjs/internal/util/errorContext.js:22:9)
    at Observable.subscribe (/.../node_modules/rxjs/dist/cjs/internal/Observable.js:26:24)
    at /.../node_modules/rxjs/dist/cjs/internal/operators/catchError.js:26:27
    at OperatorSubscriber.<anonymous> (/.../node_modules/rxjs/dist/cjs/internal/util/lift.js:14:28)
    at /.../node_modules/rxjs/dist/cjs/internal/Observable.js:30:30
    at Object.errorContext (/.../node_modules/rxjs/dist/cjs/internal/util/errorContext.js:22:9) {
  code: 4002
}
route...:  {
  route: '/404.html',
  generateTimeMS: 118,
  fileName: '/404.html',
  contentType: 'text/html'
}

my vite.config.ts file is

export default defineConfig(({ mode }) => ({
  build: {
    target: ['es2020'],
  },
  resolve: {
    mainFields: ['module'],
  },
  plugins: [
    analog({
      static: true,
      prerender: {
        routes: async () => [
          '/',
          '/support',
          '/404.html'
        ],

and the file structure is like

- src
   |- pages
       |- support
           |- (support).page.ts
       |- 404.html.ts
       |- 404.page.html

content of 404.html.ts


@Component({
  selector: "pageNotFound",
  standalone: true,
  imports: [
    FooterCtaComponent,
    RouterLink
  ],
  templateUrl: './404.page.html'
})
export default class PageNotFoundPage {
}

@brandonroberts
Copy link
Member

@anuj9196 its supposed to be 404.page.ts for a page route

@anuj9196
Copy link

anuj9196 commented Aug 9, 2024

@brandonroberts
404.page.ts is actually creating a route as /404/index.html whereas cloudflare requires /404.html to treat your website as a static website.

@DerHerrGammler
Copy link
Contributor

@anuj9196 you can add a postRenderingHook to your vite config to change the output file names like this:

postRenderingHooks: [
    // eslint-disable-next-line @typescript-eslint/require-await
    async (route: PrerenderRoute): Promise<void> => {
        const parts = route.fileName?.split("/");
        if (parts != null && parts.length > 2) {
            parts.pop();
            route.fileName = `${parts.join("/")}.html`;
        }
    },
],

This will rename all files from folder/index.html to folder.html

@brandonroberts
Copy link
Member

@DerHerrGammler Nitro also has a setting for this

nitro: {
  prerender: {
    autoSubfolderIndex: false
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants