如何在无Node.js服务器的PHP共享主机上部署Next.js应用并搭配Laravel API?
Short answer: Yes, but only if your Next.js app can be fully static (no server-side rendering, incremental static regeneration, or Next.js API routes). Here's how to make it work, plus alternatives if your app relies on Node.js-specific features.
Prerequisites
First, confirm your Next.js app doesn't use features that require a Node.js server:
- Avoid
getServerSideProps(SSR) andgetInitialProps(legacy SSR) - Ditch Next.js API routes (use Laravel's API endpoints instead)
- Disable default Image Optimization (it needs Node.js; optimize images manually or use a CDN instead)
- Skip Incremental Static Regeneration (ISR) — all pages must be generated at build time
Note: getStaticProps and getStaticPaths (static site generation) are totally compatible with static exports, so those are fine to use.
Step-by-Step Setup
1. Export your Next.js app as static files
First, generate the static version of your app:
- Add an export script to your
package.json:"scripts": { "build": "next build", "export": "next export" } - Run
npm run build && npm run export— this creates anoutfolder with all static HTML, CSS, JS, and assets.
2. Configure Next.js for your hosting path
If you're hosting the Next app at a subpath (like /app instead of the root), set the basePath in next.config.js to ensure assets and routes use the correct path:
module.exports = { basePath: '/app', assetPrefix: '/app/', }
3. Move static files to Laravel's public directory
- Copy all contents of the
outfolder into Laravel'spublicdirectory. If using a subpath, create a folder likepublic/appand paste the files there.
4. Configure Laravel to serve the Next.js app
Next.js uses client-side routing, so we need Laravel to serve the Next index.html for all non-API routes.
Option A: Next app at root domain
Add a catch-all route to routes/web.php after any other Laravel web routes (like admin panels):
// Serve Laravel's own web routes first (if you have any) Route::get('/admin', function () { return view('admin.dashboard'); }); // Catch-all for Next.js client-side routes Route::get('/{any}', function () { return file_get_contents(public_path('index.html')); })->where('any', '.*');
Update your Laravel .htaccess (in public/) to route non-existing files to Laravel's index.php:
<IfModule mod_rewrite.c> <IfModule mod_negotiation.c> Options -MultiViews -Indexes </IfModule> RewriteEngine On # Handle Authorization Header RewriteCond %{HTTP:Authorization} . RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] # Redirect Trailing Slashes If Not A Folder... RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_URI} (.+)/$ RewriteRule ^ %1 [L,R=301] # Send Requests To Front Controller... RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.php [L] </IfModule>
Option B: Next app at subpath (e.g., /app)
Add these routes to routes/web.php:
// Serve Next.js app root Route::get('/app', function () { return file_get_contents(public_path('app/index.html')); }); // Catch-all for Next.js client-side routes under /app Route::get('/app/{any}', function () { return file_get_contents(public_path('app/index.html')); })->where('any', '.*');
5. Test locally first
- Run
php artisan serveto start your Laravel server - Visit your Next app's URL (root or
/app) — verify assets load, client-side routing works, and API calls to Laravel's/apiendpoints succeed.
If your Next.js app needs Node.js features
If you can't avoid SSR, ISR, or Next.js API routes, here are your alternatives:
1. Use a host that supports both Node.js and PHP
Many providers (like DigitalOcean, AWS, Heroku, or even shared hosts like SiteGround) offer Node.js support alongside PHP. You can:
- Run the Next.js server on a separate port or subdomain, and Laravel on another
- Use Nginx as a reverse proxy to route requests to the correct server
2. Split hosting between Vercel and your PHP host
- Host Next.js on Vercel (it's optimized for Next.js and free for small projects)
- Keep Laravel on your shared PHP host
- Configure CORS in Laravel to allow requests from your Vercel domain (add your Vercel URL to
config/cors.php'sallowed_origins)
3. Rewrite SSR code to use client-side fetching
Replace getServerSideProps with client-side data fetching (e.g., using useEffect to call your Laravel API when the component mounts). This lets you statically export the app while still loading data dynamically.
内容的提问来源于stack exchange,提问作者Rafat Rashid

