forked from zeabur/zbpack
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request zeabur#135 from zeabur/yuanlin/zea-1828-zbpack-imp…
…lementation feat(lib): Serverless output for static websites and Next.js
- Loading branch information
Showing
17 changed files
with
517 additions
and
180 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package nextjs | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"os" | ||
"path" | ||
"path/filepath" | ||
"strings" | ||
|
||
cp "github.com/otiai10/copy" | ||
) | ||
|
||
// constructNextFunction will construct the first function page, used as symlinks for other function pages | ||
func constructNextFunction(zeaburOutputDir, firstFuncPage string) error { | ||
p := path.Join(zeaburOutputDir, "functions", firstFuncPage+".func") | ||
|
||
err := os.MkdirAll(p, 0755) | ||
if err != nil { | ||
return fmt.Errorf("create function dir: %w", err) | ||
} | ||
|
||
launcher, err := renderLauncher() | ||
if err != nil { | ||
return fmt.Errorf("render launcher: %w", err) | ||
} | ||
|
||
err = os.WriteFile(path.Join(p, "index.js"), []byte(launcher), 0644) | ||
if err != nil { | ||
return fmt.Errorf("write launcher: %w", err) | ||
} | ||
|
||
err = cp.Copy(".next", path.Join(p, ".next")) | ||
if err != nil { | ||
return fmt.Errorf("copy .next: %w", err) | ||
} | ||
|
||
err = cp.Copy("package.json", path.Join(p, "package.json")) | ||
if err != nil { | ||
return fmt.Errorf("copy package.json: %w", err) | ||
} | ||
|
||
outputNodeModulesDir := path.Join(p, "node_modules") | ||
err = os.MkdirAll(outputNodeModulesDir, 0755) | ||
if err != nil { | ||
return fmt.Errorf("create node_modules dir: %w", err) | ||
} | ||
|
||
var deps []string | ||
err = filepath.Walk(".next", func(path string, info os.FileInfo, err error) error { | ||
if strings.HasSuffix(path, ".nft.json") { | ||
type nftJSON struct { | ||
Files []string `json:"files"` | ||
} | ||
b, err := os.ReadFile(path) | ||
if err != nil { | ||
return fmt.Errorf("read nft.json: %w", err) | ||
} | ||
var nft nftJSON | ||
err = json.Unmarshal(b, &nft) | ||
if err != nil { | ||
return fmt.Errorf("unmarshal nft.json: %w", err) | ||
} | ||
for _, file := range nft.Files { | ||
if !strings.Contains(file, "node_modules") { | ||
continue | ||
} | ||
file = file[strings.Index(file, "node_modules"):] | ||
deps = append(deps, file) | ||
} | ||
} | ||
return nil | ||
}) | ||
if err != nil { | ||
return fmt.Errorf("walk .next: %w", err) | ||
} | ||
|
||
for _, dep := range deps { | ||
err = cp.Copy(dep, path.Join(p, dep)) | ||
if err != nil { | ||
return fmt.Errorf("copy dep: %w", err) | ||
} | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package nextjs | ||
|
||
import ( | ||
_ "embed" | ||
"encoding/json" | ||
"fmt" | ||
"os" | ||
"strings" | ||
"text/template" | ||
) | ||
|
||
//go:embed launcher.js.tmpl | ||
var launcherTemplate string | ||
|
||
// getNextConfig read .next/required-server-files.json and return the config string that will be injected into launcher | ||
func getNextConfig() (string, error) { | ||
rsf, err := os.ReadFile(".next/required-server-files.json") | ||
if err != nil { | ||
return "", fmt.Errorf("read required-server-files.json: %w", err) | ||
} | ||
|
||
type requiredServerFiles struct { | ||
Config json.RawMessage `json:"config"` | ||
} | ||
|
||
var rs requiredServerFiles | ||
err = json.Unmarshal(rsf, &rs) | ||
if err != nil { | ||
return "", fmt.Errorf("unmarshal required-server-files.json: %w", err) | ||
} | ||
|
||
var data map[string]interface{} | ||
if err := json.Unmarshal(rs.Config, &data); err != nil { | ||
return "", fmt.Errorf("unmarshal config: %w", err) | ||
} | ||
|
||
nextConfig, err := json.Marshal(data) | ||
if err != nil { | ||
return "", fmt.Errorf("marshal config: %w", err) | ||
} | ||
|
||
return string(nextConfig), nil | ||
} | ||
|
||
// renderLauncher will render the launcher.js template which used as the entrypoint of the serverless function | ||
func renderLauncher() (string, error) { | ||
nextConfig, err := getNextConfig() | ||
if err != nil { | ||
return "", fmt.Errorf("get next config: %w", err) | ||
} | ||
|
||
tmpl, err := template.New("launcher").Parse(launcherTemplate) | ||
if err != nil { | ||
return "", fmt.Errorf("parse launcher template: %w", err) | ||
} | ||
|
||
type renderLauncherTemplateContext struct { | ||
NextConfig string | ||
} | ||
|
||
var launcher strings.Builder | ||
err = tmpl.Execute(&launcher, renderLauncherTemplateContext{NextConfig: nextConfig}) | ||
if err != nil { | ||
return "", fmt.Errorf("render launcher template: %w", err) | ||
} | ||
|
||
return launcher.String(), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
process.chdir(__dirname); | ||
process.env.NODE_ENV = 'production'; | ||
process.env.__NEXT_PRIVATE_PREBUNDLED_REACT = "next" | ||
const NextServer = require('next/dist/server/next-server.js').default; | ||
const nextServer = new NextServer({ | ||
conf: {{ .NextConfig }}, | ||
dir: '.', | ||
minimalMode: true, | ||
customServer: false, | ||
}); | ||
const requestHandler = nextServer.getRequestHandler(); | ||
module.exports = async (req, res) => { | ||
const { NodeNextRequest, NodeNextResponse} = require('next/dist/server/base-http/node'); | ||
req = new NodeNextRequest(req) | ||
res = new NodeNextResponse(res) | ||
try { | ||
await requestHandler(req, res); | ||
} catch (err) { | ||
console.error(err); | ||
process.exit(1); | ||
} | ||
}; |
Oops, something went wrong.