I have a standard Google App Engine environment and am trying to serve some static files for my create-react-app
frontend, but I’m not able to do so without copying over the client/build/
files into the server/
folder.
My file structure looks like this:
.
├── app.yaml
├── package-lock.json
├── package.json
├── tsconfig.json
├── client
│ ├── build/
│ ├── package-lock.json
│ ├── package.json
│ ├── public/
│ ├── src/
│ └── tsconfig.json
└── server
├── dist/
├── package-lock.json
├── package.json
├── src/
└── tsconfig.json
What I had been doing is uploading all the source files to Google Cloud (and excluding the locally-built ones), letting it build everything in the cloud, and then at the end of the build process copying across the client files over to the server:
"build": "npm run build:client && npm run build:server && rsync -av --delete client/build/ server/build/"
but it seemed unnecessary to build files in the client and then copy them to the server.
I was thinking I’d use handlers in app.yaml
to directly serve the static files from client/
, based on the example here but also allowing my server to handle API requests. When I tried this, I added the following to app.yaml
:
handlers:
- url: /static
static_dir: client/build/static
- url: /(.*.(json|ico|js))$
static_files: client/build/1
upload: client/build/.*.(json|ico|js)$
- url: /.*
script: auto
and changed my routes in app.ts
slightly:
// Routes
app.use('/auth', authRouter);
app.use('/api', apiRouter);
...
// Serve the React app
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, '../../client/build', 'index.html')); // before it was just '../build' instead
});
but this meant that I got a 404
error whenever trying to access the frontend.
Is the correct approach simply to copy across the built files from client/
to server/
? If so, is there a reason for this, and is it better to do it locally or as part of the build step in the cloud? Otherwise, what do I need to change about the handlers or routing for it to work?