1

Note: My knowledge of JS frameworks and TS is essentially non-existent.

I'm trying to create an SPA with SSG. I have a main component I'm trying to display a webAMP in. Which needs to access document. Right now I have the code to create a webAMP object in the main-component.ts. But it's throwing this error:

ReferenceError: document is not defined
at eval (eval at runInlinedModule (file:.../node_modules/vite/dist/node/module-runner.js:1062:11), <anonymous>:19481:10)
at async ESModulesEvaluator.runInlinedModule (file:.../node_modules/vite/dist/node/module-runner.js:1062:5)
at async SSRCompatModuleRunner.directRequest (file:.../node_modules/vite/dist/node/module-runner.js:1284:61)
at async SSRCompatModuleRunner.directRequest (file:.../node_modules/vite/dist/node/chunks/dep-DBxKXgDP.js:25274:23)
at async SSRCompatModuleRunner.cachedRequest (file:.../node_modules/vite/dist/node/module-runner.js:1180:76)

I think I've tried these but found no progress:

main.component.ts

import { NgOptimizedImage } from '@angular/common';
import { Component, DOCUMENT, Inject} from '@angular/core';
import { RouterLink, RouterOutlet } from '@angular/router';
import Webamp from 'webamp';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-main',
  imports: [RouterLink, RouterOutlet, NgOptimizedImage, CommonModule],
  templateUrl: './main.component.html',
  styleUrl: './main.component.css',
})

export class MainComponent {
  constructor(@Inject(DOCUMENT) private document: Document) {
    this.musicPlayer();
  }
  musicPlayer() {
    alert("the playerrrr"); // for testing
    const webamp = new Webamp({/* ... */});
    webamp.renderWhenReady(this.document.getElementById('winamp-container') as HTMLElement);
  }
}
}
1
  • "I'm trying to create an SPA with SSG" that's a contradiction. If it's a static site, it's not a SPA... Commented Jul 1 at 17:26

2 Answers 2

1

The document object does not exist on the server, so you will be getting this error. To handle this on the HTML, use the @defer to render a certain HTML block only on the browser. The @defer works only on the browser when defined with basic configuration.

@defer() {
  <app-some-component/>
}

When working with typescript code, we can use the afterNextRender hook, to execute logic only on the browser.

constructor(@Inject(DOCUMENT) private document: Document) {
  afterNextRender(() => {
    this.musicPlayer();
  });
}
Sign up to request clarification or add additional context in comments.

2 Comments

I've implemented this and still face the issue, what am I doing wrong and what should I look into to fix it?
it does seem to work when I try using document for other tests but not when initializing webamp (WITHOUT rendering it). For one I didn't think initializing it accessed document and for two if it did shouldn't it still not cause this error?
0

Along with the correct answer, I found I needed to conditionally import webamp, that's it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.