質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Express

ExpressはNode.jsのWebアプリケーションフレームワークです。 マルチページを構築するための機能セットおよびハイブリッドのWebアプリケーションを提供します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

1回答

1385閲覧

ReactのSSR(with Express+Webpack)を試したらUnexpected tokenになる

askyq

総合スコア46

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Express

ExpressはNode.jsのWebアプリケーションフレームワークです。 マルチページを構築するための機能セットおよびハイブリッドのWebアプリケーションを提供します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

0クリップ

投稿2021/08/07 09:20

以下のサイトの通りに新規プロジェクトを立ち上げて、ReactのSSRをセットアップしました。
こちらの環境は、以下の通りにすれば再現できると思います。
https://www.digitalocean.com/community/tutorials/react-server-side-rendering-ja

試したこと

エラーが出るがデバッグ自体はできる

npm run dev:build-serverは、以下のエラーが発生するもののサーバー自体は正常に動作します。
ただしHTMLを確認すると、うまくSSRによる静的レンダリングができていませんでした。

ERROR in ./server/index.js Module not found: Error: Can't resolve '../src/App.js' in '/Users/kmy/Develop/react/server' @ ./server/index.js 6:0-32

webpackの「-w」を外したらビルドできない

将来的にこのアプリをサーバーにデプロイすることを考えており、そのためにはExpressサーバーのソースコード(server/index.js)をproductionでビルドして成果物をserver-buildフォルダに生成する必要があります。
webpackの-wオプションはファイルの変更をリアルタイムで監視しますが、これは開発用のオプションであり、製品用ビルドでは必要ありません。なのでこれを外してビルドを試みました。

"scripts": { ... "build-server": "NODE_ENV=production webpack --config webpack.server.js --mode=production", },

しかしnpm run build-serverでビルドしようとするとこのようなエラーが発生し、server-buildフォルダは生成されませんでした。

ERROR in ./server/index.js Module not found: Error: Can't resolve '../src/App.js' in '/Users/kmy/Develop/react/server' @ ./server/index.js 6:0-32

対処:jsxのインポートに対応する

エラーが起きたのはserver/index.jsの以下の行であると考えられます。

js

1import App from '../src/App';

この行は、src/App.jsxをインポートします。しかしExpressサーバーのビルドにあたって、拡張子jsxをもつファイルが認識されないのではないかと考えました。
そこで、webpack.server.jsに以下の記述を追加しました。

resolve: { extensions: ['.js', '.jsx'], }

対処:JSX記法のビルドに対応する

しかし、これでビルドしようとすると以下のエラーが発生しました。

ERROR in ./src/App.jsx 7:4 Module parse failed: Unexpected token (7:4) You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders | function App() { | return ( > <div className="App"> | <header className="App-header"> | <img src={logo} className="App-logo" alt="logo" /> @ ./server/index.js 6:0-29

これはJSX記法のロードに対応できていないと考え、webpack.server.jsの設定を以下のように変更しました。

module: { rules: [ { test: /.(js|jsx)$/, exclude: /node_modules/, loader: 'babel-loader', options: { presets: ["@babel/preset-env", "@babel/preset-react"] } }

対処:SVGとCSSのビルドに対応する

しかし上記でビルドしようとすると、また以下のエラーが発生しました。

ERROR in ./src/App.css 1:0 Module parse failed: Unexpected token (1:0) You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders > .App { | text-align: center; | } @ ./src/App.jsx 3:0-19 @ ./server/index.js ERROR in ./src/logo.svg 1:0 Module parse failed: Unexpected token (1:0) 以下略

これは、App.jsxファイル内にある以下のimport文が引き起こしたエラーであると思われます。

js

1import logo from './logo.svg'; 2import './App.css';

そこで、これらのファイルのローダーをwebpack.server.jsに追加しました。

js

1 module: [ 2 rules: [ 3 // ... 4 { 5 test: [/.bmp$/, /.gif$/, /.jpe?g$/, /.png$/, /.svg$/], 6 loader: require.resolve('url-loader'), 7 options: { 8 limit: 0, 9 name: 'static/media/[name].[hash:8].[ext]', 10 }, 11 }, 12 { 13 test: /.(css)$/, 14 exclude: /node_modules/, 15 loader: ['style-loader', 'css-loader'] 16 }

結果として、ビルドは成功し、server-build/index.jsファイルが生成されました。

問題:サーバーを起動しようとするとエラーが起きる

実際の環境に配置した場合を考慮して、ビルドしたserver-build/index.jsの起動をnode server-build/index.jsで試みます。
しかし、以下のエラーが発生し、サーバーの起動に失敗しました。

ReferenceError: document is not defined

ビルドによって生成されたserver-build/index.jsを確認すると、どうやら本来ブラウザ上で実行すべきReactのコードが、サーバーサイドのプログラムの中に混じってしまったようなのです。

私の対処がどの段階から間違っていたのか調べようにも、どのサイトやStackoverflowの質問も、そもそもimport '../src/App'が正常におこなえることを前提にことを進めているのです。したがってどのように対処すればいいのか分かりません。
ReactのSSRで正常にビルドできるようにするためには、どのようにすればいいのでしょうか?

今回インストールしたパッケージのバージョン

"dependencies": { "@babel/plugin-transform-react-jsx": "^7.14.9", "@testing-library/jest-dom": "^5.14.1", "@testing-library/react": "^11.2.7", "@testing-library/user-event": "^12.8.3", "express": "^4.17.1", "react": "^17.0.2", "react-dom": "^17.0.2", "react-scripts": "^4.0.3", "type-fest": "^0.21.3", "web-vitals": "^1.1.2" }, "devDependencies": { "@babel/core": "^7.15.0", "@babel/preset-env": "^7.15.0", "@babel/preset-react": "^7.14.5", "babel-loader": "^8.1.0", "babel-preset-env": "^1.7.0", "babel-preset-react": "^6.24.1", "nodemon": "^2.0.12", "npm-run-all": "^4.1.5", "webpack": "^4.44.2", "webpack-cli": "^4.7.2", "webpack-node-externals": "^3.0.0" }

環境

macOS Catalina
VSCode

kmy@KMYnoMac-mini react % node --version v12.18.0 kmy@KMYnoMac-mini react % npm --version 7.19.1

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

ごめんなさい、投稿した直後で申し訳ないのですがNext.jsに変更しました。
https://www.forcia.com/blog/001559.html

というのも、今回参考にしたサイトですがこれは日本語への翻訳版でして、原文を以下のURLから確認しました。
https://www.digitalocean.com/community/tutorials/react-server-side-rendering
確認したところ、以下の文章が書いてありました。これは日本語の翻訳版には書いていないものです。

Warning: The code provided in this tutorial is for educational purposes and is not intended for production use. Alternatively, Next.js offers a modern approach to creating static and server-rendered applications built with React.

これにしたがい、Next.jsを使うように修正します。

投稿2021/08/07 09:48

編集2021/08/07 11:32
askyq

総合スコア46

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問