0

Please tell me how to set up the preact-render-to-string on the express.

I built it reading the above links. The source code is on there, but I'm not used to node I don't know how to execute it(Or I don't know if I'm failing to build the environment.).

I believe my installation procedure can be found in package.json(dependencies and devDependencies). So, below is my package.json.

My package.json:

{
  "name": "y",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.1"
  },
  "devDependencies": {
    "preact": "^10.5.14",
    "preact-render-to-string": "^5.1.19"
  }
}

My app.js (Same as Document): I didn't know what to do with the file name, so I used app.js.

import express from 'express';
import { h } from 'preact';
import render from 'preact-render-to-string';
/** @jsx h */

// silly example component:
const Fox = ({ name }) => (
    <div class="fox">
        <h5>{ name }</h5>
        <p>This page is all about {name}.</p>
    </div>
);

// basic HTTP server via express:
const app = express();
app.listen(8080);

// on each request, render and return a component:
app.get('/:fox', (req, res) => {
    let html = render(<Fox name={req.params.fox} />);
    // send it back wrapped up as an HTML5 document:
    res.send(`<!DOCTYPE html><html><body>${html}</body></html>`);
});

Run and Error:

$ node app.js  
src/pr/ex/app.js:1
import express from 'express';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at Object.compileFunction (node:vm:352:18)
    at wrapSafe (node:internal/modules/cjs/loader:1031:15)
    at Module._compile (node:internal/modules/cjs/loader:1065:27)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:79:12)
    at node:internal/main/run_main_module:17:47

I think I am running it wrong or failed to build the environment, what can I do to make it run successfully?

node is installed with nodebrew. The current status is as follows.

$ nodebrew list
v16.6.2

current: v16.6.2

Edit:

I tried the answer.

add the top-level "type" field with a value of "module"

The error SyntaxError: Cannot use import statement outside a module is gone and different error occurred.

$ node app.js   
file:///src/pr/ex/app.js:8
    <div class="fox">
    ^

SyntaxError: Unexpected token '<'
    at Loader.moduleStrategy (node:internal/modules/esm/translators:146:18)
    at async link (node:internal/modules/esm/module_job:67:21)

Since I am using preact (I must be using htm internally), it is odd that Unexpected token '<' would be an error.

package.json after editing:

{
  "name": "y",
  "version": "1.0.0",
  "type": "module",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.1"
  },
  "devDependencies": {
    "preact": "^10.5.14",
    "preact-render-to-string": "^5.1.19"
  }
}
shingo.nakanishi
  • 2,045
  • 2
  • 21
  • 55
  • "I must be using HTM internally" Sorry, I don't follow. You're definitely not using HTM, but you're authoring in JSX. You need to run your app through Babel (which is what that JSX comment is for at the top of the file). – rschristian Sep 02 '21 at 06:12
  • It was JSX? If so, I must have been mistaken. I know about Babel itself, but I don't know how to run it. Can you please help me? – shingo.nakanishi Sep 02 '21 at 06:33
  • I always use Babel with a framework like NextJS or a CDN, so I don't know how to use it with this question. – shingo.nakanishi Sep 02 '21 at 06:34
  • Yes, that component is JSX. `
    ...
    ` is not valid JS, hence the error being thrown. You can look up how to use Babel with Express (there's plenty of full examples out there) or switch to using HTM, which doesn't need to be transpiled.
    – rschristian Sep 02 '21 at 06:38
  • When I used `preact-cli` in other directory, Bable and HTM were working without my awareness. For this reason, I thought it would compile on `import render from 'preact-render-to-string';`, but it seems to be different, so I will look into it. – shingo.nakanishi Sep 02 '21 at 06:52
  • Preact-CLI doesn't use HTM. An import statement doesn't transpile the file. It just gives you access to exported members from that module. – rschristian Sep 02 '21 at 07:03
  • I see. I guess I misunderstood a lot of things. – shingo.nakanishi Sep 02 '21 at 07:11

1 Answers1

0

Possible solutions:

  1. Use require:
const express = require('express')
const { h } = require('preact')
  1. Save your app.js file as a .mjs file (Node13+ only)

  2. Add { type: 'module' } in your package.json

Kim Skogsmo
  • 441
  • 3
  • 13