íì¬ API ê²œë¡ ëë íìŽì§ìì íìŒì ìœì ì ììµëë€.
__dirname
겜ë¡ë¥Œ ì¬ì©íì¬ fs.readFile
륌 ížì¶íê³ "ê·žë¥ ìë"íëë¡ íê³ ì¶ìµëë€.
ìŽê²ì ê°ë° ë° ìì° ëªšëìì ìëíŽìŒ í©ëë€.
ìŽê²ì ìŒë¶ ì©ëìì @zeit/webpack-asset-relocator-loader
ì íµí©íŽìŒ í ìë ììµëë€. ìŽ íë¬ê·žìžì ìŽë¬í ì íì ì구 ì¬íì ì²ëŠ¬í©ëë€.
ê·žë¬ë íì ì¬íì ìëëë€. __dirname
ë° __filename
(ìë ëë cwd êž°ë° ê²œë¡ ìì)ììë§ _ë§_ ìëíë í목ìŽë©Ž êŽì°®ìµëë€.
ìì:
// pages/api/test.js
import fs from 'fs'
import path from 'path'
export default (req, res) => {
const fileContent = fs.readFileSync(
path.join(__dirname, '..', '..', 'package.json'),
'utf8'
)
// ...
}
ì°žê³ : ìì âïž ìì 륌
require
ììŒ ì ìë€ë ê²ì ìê³ ìì§ë§ ê·žê² ìì ìŽ ìëëë€. ð
API 겜ë¡ë¥Œ ì¬ì©íì¬ íìŒ ì ë¡ë륌 구ííë €ê³ ìëíë ê²ì ë ë²ì§žë¡ ìíìµëë€. íìŒì ì ë¡ëí ì ìì§ë§ S3 ë²í·ì ì ë¡ëíë €ë©Ž ë€ì ì¡ìžì€í ì ììŽìŒ í©ëë€.
ëë ìŽê²ì ë ë²ì§ž! ëí ëë í 늬륌 ìœì ì ìë ê²ì ì°ëŠ¬ íì¬ì ì¬ì©ì ë§€ì° ì€ìí©ëë€. í 구ì±ì ë° ëžë¡ê·ž ê²ì묌곌 ê°ì ë°ìŽí°ë¥Œ ìœí ìž ëë í 늬ì 볎êŽíë¯ë¡ ëë í 늬ì 몚ë íìŒì ì구íë ë°©ë²ì ì°Ÿê³ ììµëë€.
ìì PRë¡ íŽê²°ë©ëë€! âïž ð
fs.writeFile
ê·žê² ê°ë¥íê°ì? ì륌 ë€ìŽ /api/route
ì ê²ìë ì¹í
ì êž°ë°ìŒë¡ JSON íìŒì ë§ë€ê³ ì ì¥í©ëë€.
@marlonmarcello , ìŽê²ìŽ ê°ë¥í ê²ì ëë€. ê³ì ì§ìŒëŽ 죌ìžì ð
ìŽê±° ìŽë¯ž íŽê²°ëìŽ?
ìì§, ë¹ì ì #8334륌 구ë í ì ììµëë€
@huv1k ê°ì¬í©ëë€!
ìŽ ìì ì ë 빚늬 ì§ííë ë° ëììŽ ëë ë°©ë²ìŽ ììµëê¹?
죌목í ê°ì¹: TypeScript륌 ì¬ì©íë ê²œì° ìŽë¯ž JSON íìŒì 몚ëë¡ ì§ì ê°ì žì¬ ì ììµëë€( resolveJsonModule
ê° true
ìì tsconfig.json
). ì:
import myJson from '../../../some/path/my.json';
JSON ê°ì²Žì 몚ìë ìëìŒë¡ íì ìŒë¡ ì¬ì©ëêž° ë묞ì ìë ìì± êž°ë¥ìŽ ì ë§ ì¢ìµëë€.
ëŽê° ì¬ì©íë íŽê²° ë°©ë²:
# next.config.js
module.exports = {
serverRuntimeConfig: {
PROJECT_ROOT: __dirname
}
}
겜ë¡ê° íìí ìì¹ì
import fs from 'fs'
import path from 'path'
import getConfig from 'next/config'
const { serverRuntimeConfig } = getConfig()
fs.readFile(path.join(serverRuntimeConfig.PROJECT_ROOT, './path/to/file.json'))
ìŽê²ìŽ íì¬ íìŒì ìëì ìž ê²œë¡ê° ìë ì°žì¡° íìŒì íìì±ì íŽê²°íì§ ëª»íë€ë ê²ì ìê³ ìì§ë§ ìŽê²ì ëŽ ë§€ì° êŽë šë ì¬ì© ì¬ë¡( /public/images
íŽëìì ìŽë¯žì§ íìŒ ìœêž°)륌 íŽê²°í©ëë€.
PRìì 볎ë ìŽê²ìŽ ì¡°êž ë³ê²œëììµëë€ - íì¬ ê³íìŽ ë¬Žììžì§ì ëí ì ë°ìŽížê° ììµëê¹(ëë ê·žë ì§ ììì§)? ì¶êµ¬íê³ ì¶ì§ ìì ëª ê°ì§ ì ëµìŽ ìë ê² ê°ìµëë€. 목ë¡ì ìì±íë ê²ì ìŒëì ëìžì. + êž°ì¬ìë€ìŽ ìŽê²ì ìëí ì ìë ìŽì ë 묎ìì ëê¹?
ìŽê²ì Next.jsìì nexus ì ì¬ì© ì
ëŽê° ì¬ì©íë íŽê²° ë°©ë²:
# next.config.js module.exports = { serverRuntimeConfig: { PROJECT_ROOT: __dirname } }
겜ë¡ê° íìí ìì¹ì
import fs from 'fs' import path from 'path' import getConfig from 'next/config' const { serverRuntimeConfig } = getConfig() fs.readFile(path.join(serverRuntimeConfig.PROJECT_ROOT, './path/to/file.json'))
ìŽê²ìŽ íì¬ íìŒì ìëì ìž ê²œë¡ê° ìë ì°žì¡° íìŒì íìì±ì íŽê²°íì§ ëª»íë€ë ê²ì ìê³ ìì§ë§ ìŽê²ì ëŽ ë§€ì° êŽë šë ì¬ì© ì¬ë¡(
/public/images
íŽëìì ìŽë¯žì§ íìŒ ìœêž°)륌 íŽê²°í©ëë€.
ë©ì§ ëšì. ë륌 ìíŽ ìŒíë€.
ëë ìŽê²ì ìíŽ ìë¡ìŽ getStaticProps
ë°©ë²ì ì¬ì©íìµëë€(#9524ìì). ìŽ ë°©ë²ì íì¬ ë¶ìì í ê²ìŒë¡ íìëìŽ ìì§ë§ ê³µìì ìŒë¡ ì ë¬íë ê²ì ëíŽ Next.js íì ì¢ì ì§ììŽ ìë ê² ê°ìµëë€.
ì:
export async function unstable_getStaticProps() {
const siteData = await import("../data/pages/siteData.json");
const home = await import("../data/pages/home.json");
return {
props: { siteData, home }
};
}
@ScottSmith95 ìŽê²ì ì¬ì©íë ê³µê° ìì€ íë¡ì ížê° ììµëê¹? ìŽë€ 몚ìµìŒì§ ê¶êží©ëë€.
ìŽ íë¡ì ížë ìì§ ì€í ìì€ê° ìëì§ë§ ì§ë¬žìŽ ë ììŒë©Ž ëŽ êµ¬ì±ì ë ê³µì íŽ ëëŠ¬ê² ìµëë€.
@ScottSmith95 _몚ë _ ì§ë¬žìŽ ììµëë€ ð
src
?)@Svish ì°ëŠ¬ë íë¡ì íž ëŽì /dataì ë°ìŽí° íìŒì ì ì¥í©ëë€. (íìŽì§ë /src/pragesê° ìëëŒ /pagesì ììµëë€.) ìŽ íìŽì§ êµ¬ì± ììë ë€ì곌 ê°ìµëë€(propsë Ʞ볞 ëŽë³ŽëŽêž°ìž Home êµ¬ì± ììë¡ ì ì¡ëš).
// /pages/index.js
const Home = ({ siteData, home }) => {
return (
<>
<Head>
<meta name="description" content={siteData.siteDescription} />
<meta name="og:description" content={siteData.siteDescription} />
<meta
name="og:image"
content={getAbsoluteUrl(siteData.siteImage, constants.siteMeta.url)}
/>
</Head>
<section className={`container--fluid ${styles.hero}`}>
<SectionHeader section={home.hero} heading="1">
<div className="col-xs-12">
<PrimaryLink
href={home.hero.action.path}
className={styles.heroAction}
>
{home.hero.action.text}
</PrimaryLink>
</div>
</SectionHeader>
<div className={styles.imageGradientOverlay}>
<img src={home.hero.image.src} alt={home.hero.image.alt} />
</div>
</section>
</>
);
};
ëì 겜ë¡ê° ìë ê³ êž íìŽì§ì ê²œì° ë€ì곌 ê°ìŽ ìŽ ë°ìŽí°ë¥Œ ê°ì žìµëë€.
// /pages/studio/[member.js]
export async function unstable_getStaticProps({ params }) {
const siteData = await import("../../data/pages/siteData.json");
const member = await import(`../../data/team/${params.member}.json`);
return {
props: { siteData, member }
};
}
ëì 겜ë¡ë¥Œ ì¬ì©íë©Ž ë°°í¬ê° ì ë§ ìííê² ì§íëë©° getStaticPaths()
ê° íìí©ëë€. ìŽì ëí 묞ì ë RFC 륌 íìžíë
// /pages/studio/[member.js]
export async function unstable_getStaticPaths() {
const getSingleFileJson = async path => await import(`../../${path}`);
// These utility functions come from `@asmallstudio/tinyutil` https://github.com/asmallstudio/tinyutil
const directoryData = await getDirectory(
"./data/team",
".json",
getSingleFileJson,
createSlugFromTitle
);
const directoryPaths = directoryData.reduce((pathsAccumulator, page) => {
pathsAccumulator.push({
params: {
member: page.slug
}
});
return pathsAccumulator;
}, []);
return directoryPaths;
}
@ScottSmith95 ì ë§
next export
?getStaticPaths
ê° ê²œë¡ ë§€ê°ë³ì 목ë¡ì ë°ííë€ë ì¬ì€ì ì ê° ì¬ë°ë¥Žê² ìŽíŽíëì? ê·žë° ë€ì ê° ë ëë§ì ëíŽ getStaticProps
ì íëì© (ë€ììŒë¡) ê³µêžë©ëê¹?getStaticPaths
ììŽ getStaticProps
륌 ì¬ì©í ì ììµëê¹?getStaticProps
ìì _app
? ì륌 ë€ìŽ ë¡ëíë €ë ì¬ìŽíž ì 첎 구ì±ìŽë ìŽì ì ì¬í ê²ìŽ ìë€ë©Ž?apiëì?? ìŽë¬í íí¬ë íìŽì§ì©ìŽì§ë§ APIë ìŽë»ìµëê¹?
íŒëì€ë¬ìì. ë€ì 구ì±ìì _dirnameì env ë³ìë¡ ì€ì í ì ìììµëë€. ë°ëŒì APIìì íìŒ ìì€í ì ì¡ìžì€í ì ììì§ë§ ë¡ì»¬ììë§ ìëíìµëë€. ì§êž ë°°í¬í í ì€ë¥ê° ë°ìíìµëë€. ë°°í¬ í ìëíì§ ìë ìŽì ë 묎ìì ëê¹?
@josias-r 죌ì 묞ì ë ìŒë°ì ìŒë¡ ìœì íìŒìŽ ë°°í¬ì í¬íšëì§ ìëë€ë ì ìŽì§ë§ íìŒì í¬íšíë ë°©ë²ê³Œ íìŒ ì íì ë°ëŒ ë€ëŠ
ëë€( js
/ json
ìŒë°ì ìŒë¡ êŽì°®ì§ë§ .jade
ì ê°ì ë€ë¥ž íìŒ íìì íìŒì ìœê³ ì²ëŠ¬íêž° ìíŽ ë³ëì @now/node
ëë€/ë°°í¬ë¥Œ ì¬ì©íë ê²ê³Œ ê°ìŽ ìŽë¥Œ ì²ëŠ¬íë ë첎 ë°©ë²ìŽ íìí©ëë€.
ì€ë¥ì ëíŽ ë ììží ì€ëª í ì ìë€ë©Ž ëêµ°ê°ê° ë¹ì ì ëìž ì ììµëë€.
@BrunoBernardino ì€ì ë¡ ëŽ src íŽë ìì JSON íìŒì ì°žì¡°íê³ ìììµëë€. ê·žë¬ë ì€ì ë¡ë ìŽë¯ž ë°°í¬ì ì€íší fs.readdirSync(my_dirname_env_var)
ë©ìëì
ëë€. ë°ëŒì ë°°í¬ í íŽë¹ ëë í ëŠ¬ê° ì í ì¡Žì¬íì§ ìë ê² ê°ìµëë€. ë€ìì ëŽ API륌 íµíŽ jsonì ëí ì 첎 겜ë¡ì ì¡ìžì€íë €ê³ í ë ì»ë ê²ì
ëë€.
ERROR Error: ENOENT: no such file or directory, open '/zeit/3fc37db3/src/content/somejsonfilethatexists.json'
ê·žëŠ¬ê³ ëŽê° ìžêžíë¯ìŽ ìŽê²ì ë¹ëíê³ npm start
륌 ì€íí ë ë¡ì»¬ìì ìëí©ëë€.
@josias-r ê°ì¬í©ëë€! ëì (ë°°í¬ë¥Œ ëë²ê·žíêž° ìíŽ) ìë 겜ë¡(ë³ì ìì)ë¡ fs.readdirSync
륌 ìëíŽ ë³Žì
šìµëê¹? ëë ìŒë°ì ìŒë¡ ìëíë€ë ê²ì ë°ê²¬íìŒë©°, ê·žë ë€ë©Ž ìŽêž°í íë¡ìžì€( getInitialProps
ëë êž°í)ì ìŽëê°ì íŽë¹ ìœë륌 ìì±í ì ììŒë¯ë¡ ë°°í¬ íë¡ìžì€ë íŽë¹ íìŒìŽ íìíë€ë ê²ì íìží ë€ì ì€ì ìœë/ë¡ì§ìì varë¡ íìŒì ê³ì ìœìµëë€. ê¹ëíì§ë ìì§ë§ ìŽê²ìŽ ì§ìë ëê¹ì§ ìëí©ëë€. ìŽë€ 겜ì°ìë __dirname
ì¬ì©íë ê²ë íšê³Œê° ìë€ê³ ìê°í©ëë€.
@BrunoBernardino ë£šíž ìë ê²œë¡ ./
ìì ììíë íìŒ ížëŠ¬ë¥Œ ë§ë€ ì ìììµëë€. ëŽê° ì»ì ê²ì ë€ì JSONìŽììµëë€(ë
žë 몚ëìŽ ëìŽëì§ ìì).
{
"path": "./",
"name": ".",
"type": "folder",
"children": [
{
"path": ".//.next",
"name": ".next",
"type": "folder",
"children": [
{
"path": ".//.next/serverless",
"name": "serverless",
"type": "folder",
"children": [
{
"path": ".//.next/serverless/pages",
"name": "pages",
"type": "folder",
"children": [
{
"path": ".//.next/serverless/pages/api",
"name": "api",
"type": "folder",
"children": [
{
"path": ".//.next/serverless/pages/api/posts",
"name": "posts",
"type": "folder",
"children": [
{
"path": ".//.next/serverless/pages/api/posts/[...id].js",
"name": "[...id].js",
"type": "file"
}
]
}
]
}
]
}
]
}
]
},
{
"path": ".//node_modules",
"name": "node_modules",
"type": "folder",
"children": ["alot of children here ofc"]
},
{ "path": ".//now__bridge.js", "name": "now__bridge.js", "type": "file" },
{
"path": ".//now__launcher.js",
"name": "now__launcher.js",
"type": "file"
}
]
}
JSON íìŒìŽ ëëœë ê² ê°ìµëë€. ììì ì ìí ê²ì²ëŒ ìœë륌 íµíŽ íìŒì í¬íšìí€ì šìµëê¹? 죌ì 묞ì ë ë°°í¬ ì€íìŽ íì ëì 겜ë¡ë¥Œ ì ííë ê²ì ìëë¯ë¡ ì ì 겜ë¡ë¥Œ ê°ì ë¡ ì ì©íë ê²ìŽ 곌거ìë íšê³Œì ìŽìë€ë ê²ì ëë€(ì€ì ìœëê° ì€íë íìë ìì§ë§ êŽë š íìŒìŽ í¬íš). ê·žê² ë§ìŽ ëëì?
@BrunoBernardino ë¹ API ì룚ì
ìŒë¡ ì ííìµëë€. íŽëìì íìŒì ëì ìŒë¡ ì구íê³ ìŽ íìŒì ëŽì©ë§ íìíë¯ë¡ import()
ë©ìë륌 ì¬ì©í ì ììµëë€. ëë íŽí¹ì²ëŒ 볎ìŽêž° ë묞ì ìŽë° ììŒë¡ íê³ ì¶ì§ë ììì§ë§ 볞ì§ì ìŒë¡ ëŽ API ìëí¬ìžížê° ìííì ê²ê³Œ ëìŒí ìì
ì ìííê³ ììµëë€.
... ì ì íŽëì íìŒì ë£ìŒë €ê³ íì§ë§ ìëíì§ ìììµëë€. ê·žë¬ë íìŒ ìì€í
ì ì¡ìžì€íë ê²ìŽ 믞ëì ê°ë¥íꞰ륌 ë°ëëë€.
ëë ëí íŽí€ ì룚ì ì ìì¡ŽíŽìŒ íì§ë§ ìŽê²ìŽ 곧 ì¶ìë ê²ìŽë©° ìŽë¬í ì¬ì© ì¬ë¡ê° "ììë ëë¡" ì§ìëêž° ë묞ì ë ë§ì ì¬ëë€ìŽ Next륌 íë¡ëì ì€ë¹ ìíë¡ ë³Žêž° ììí ê²ì ëë€.
ëŽê° ì¬ì©íë íŽê²° ë°©ë²:
# next.config.js module.exports = { serverRuntimeConfig: { PROJECT_ROOT: __dirname } }
겜ë¡ê° íìí ìì¹ì
import fs from 'fs' import path from 'path' import getConfig from 'next/config' const { serverRuntimeConfig } = getConfig() fs.readFile(path.join(serverRuntimeConfig.PROJECT_ROOT, './path/to/file.json'))
ìŽê²ìŽ íì¬ íìŒì ìëì ìž ê²œë¡ê° ìë ì°žì¡° íìŒì íìì±ì íŽê²°íì§ ëª»íë€ë ê²ì ìê³ ìì§ë§ ìŽê²ì ëŽ ë§€ì° êŽë šë ì¬ì© ì¬ë¡(
/public/images
íŽëìì ìŽë¯žì§ íìŒ ìœêž°)륌 íŽê²°í©ëë€.ë©ì§ ëšì. ë륌 ìíŽ ìŒíë€.
ë¡ì»¬ ê°ë°ììë ì벜íê² ìëíì§ë§ now
ë°°í¬í ëë ìëíì§ ìë ê² ê°ìµëë€.
ENOENT: no such file or directory, open '/zeit/41c233e5/public/images/my-image.png'
at Object.openSync (fs.js:440:3)
at Object.readFileSync (fs.js:342:35)
at getEmailImage (/var/task/.next/serverless/pages/api/contact/demo.js:123:52)
at module.exports.7gUS.__webpack_exports__.default (/var/task/.next/serverless/pages/api/contact/demo.js:419:87)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at async apiResolver (/var/task/node_modules/next/dist/next-server/server/api-utils.js:42:9) {
errno: -2,
syscall: 'open',
code: 'ENOENT',
path: '/zeit/41c233e5/public/images/my-image.png'
}
ê³µì© íŽëê° ê²œë¡ë¡ ìŽëëë€ë ê²ì ìê³ ììŒë¯ë¡ íë¡ëì í겜ìì Ʞ볞 íŽëìì ê°ì ë¡ ê²ìíëë¡ ìëíì§ë§ ì¬ì í ëìŒí 결곌륌 ì»ììµëë€.
ENOENT: no such file or directory, open '/zeit/5fed13e9/images/my-image.png'
at Object.openSync (fs.js:440:3)
at Object.readFileSync (fs.js:342:35)
at getEmailImage (/var/task/.next/serverless/pages/api/contact/demo.js:124:52)
at module.exports.7gUS.__webpack_exports__.default (/var/task/.next/serverless/pages/api/contact/demo.js:331:87)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at async apiResolver (/var/task/node_modules/next/dist/next-server/server/api-utils.js:42:9) {
errno: -2,
syscall: 'open',
code: 'ENOENT',
path: '/zeit/5fed13e9/images/my-image.png'
}
@PaulPCIO ë¹ì ìŽ ê²ªê³ ìë 묞ì ë .json
, .js
ëë .ts
íìŒìŽ ìëêž° ë묞ì
ëë€. /public
ìëì íìŒì CDNì "ë°°í¬"ëì§ë§ ëë€(AFAIK)ìë ë°°í¬ëì§ ììŒë¯ë¡ ìŽ ê²œì° includeFiles
ì¬ì©íë ì ì© ëë€( @now/node
) ë°°í¬ê° íìí©ëë€ includeFiles
, ëë íŽë¹ ëšìŒ íìŒë§ íìí ê²œì° base64
ë¡ ë³ííê³ varë¡ ì¬ì©íììì€(ì ì© íìŒì ìë ìë ).
@BrunoBernardino ììëë¡ ê°ì¬í©ëë€ base64
ë°©ìì ì¬ì©íê² ìµëë€
ë°°í¬ë í겜ìì __dirnameì ëí ìŒë¶ íŽê²° ë°©ë²ìžê°ì?
@NicolasHz ììží
@BrunoBernardino ëŽ ì견ì í¬íší ë§ì§ë§ ì견ì 볎멎 "map _dirname
in the next config" íŽí¹ìŽ ë°°í¬ìì ìëíì§ ìëë€ê³ íì í©ëë€. ì¬ì§ìŽ w/js ë° JSON íìŒ. ì ìŽë now
ë°°í¬ì ê²œì° ì¬ì©ì ì§ì ë°°í¬ìë í¬íšëì§ ììµëë€.
@BrunoBernardino ë°°í¬ë í겜ì ë¡ì»¬ 겜ë¡ë¥Œ
@NicolasHz ìê² ìµëë€ . ì, ìœê³ /ì¡ìžì€íŽìŒ íë íìŒì ì¢ ë¥ì ë°ëŒ ìì ì룚ì ì€ íë륌 ì¬ì©íŽìŒ í©ëë€.
íìžë§ íë©Ž config.jsê° ë°°í¬ìì ìëíì§ ììµëë€.
ëŽê° ì¬ì©íë íŽê²° ë°©ë²:
# next.config.js
module.exports = {
env: {
PROJECT_DIRNAME: __dirname,
},
}
ê·žëŠ¬ê³ ê²œë¡ê° íìí API ì ììì(allPosts íŽëìë ë§í¬ë€ìŽ íìì 몚ë ëžë¡ê·žê° í¬íšëìŽ ììŒë©° íë¡ì íž ë£šížì ììµëë€)
import fs from 'fs'
import { join } from 'path'
const postsDirectory = join(process.env.PROJECT_DIRNAME, 'allPosts')
ì§ì ê°ë°ì ì벜íê² ìëíê³ ììµëë€.
ê·žë¬ë ì§êž zeitì ë°°í¬í ë ìŽ ì€ë¥ê° ë°ìí©ëë€.
[POST] /api/postsApi
11:00:13:67
Status:
500
Duration:
8.1ms
Memory Used:
76 MB
ID:
kxq8t-1585546213659-5c3393750f30
User Agent:
axios/0.19.2
{
fields: [ 'title', 'date', 'slug', 'author', 'coverImage', 'excerpt' ],
page: 1
}
2020-03-30T05:30:13.688Z 572075eb-4a7a-47de-be16-072a9f7005f7 ERROR Error: ENOENT: no such file or directory, scandir '/zeit/1cc63678/allPosts'
at Object.readdirSync (fs.js:871:3)
at getPostSlugs (/var/task/.next/serverless/pages/api/postsApi.js:306:52)
at module.exports.fZHd.__webpack_exports__.default (/var/task/.next/serverless/pages/api/postsApi.js:253:86)
at apiResolver (/var/task/node_modules/next/dist/next-server/server/api-utils.js:48:15)
at processTicksAndRejections (internal/process/task_queues.js:97:5) {
errno: -2,
syscall: 'scandir',
code: 'ENOENT',
path: '/zeit/1cc63678/allPosts'
}
@BrunoQuaresma ì ê°ì @sjcodebook ì ê·ž íŽê²° ë°©ë²ìŽ ë¡ì»¬ììë§ ìëíë€ê³ ë§íìµëë€. ëë ì¬ì í ëë€ê° íìŒ ìì€í
ì ì¡ìžì€íêž° ìíŽ ë³ëì @now/node
ë°°í¬ë¥Œ ì¬ì©íê³ ììŒë©° ì± ì첎ì ìì²ì íµíŽ íŽë¹ íìŒì ížì¶í©ëë€(ëë ë°°í¬íêž° ì ì íìí ì ì 결곌 ìì±). ì¢ ë¯žì³€ì§ë§ ìëí©ëë€.
ìë íìžì @BrunoBernardino... 컀ì€í ë žë ìë²ê° ìë ë³ëì íë¡ì ížë¥Œ ë§ìíìë 걎ê°ì?
ê·žë¬ë ì¡ìžì€í ì ìë ê²œì° " includeFiles " ì€ì ìŽ ìë ìŽì 륌 ìŽíŽí ì ììµëë€. ð€
@valse ëìŒí íë¡ì ížì ìì ì ììµëë€. ë€ìì ëŽ now.json
ì ì€ëí«ì
ëë€.
{
"builds": [
{
"src": "next.config.js",
"use": "@now/next"
},
{
"src": "lambdas/**/*.ts",
"use": "@now/node",
"config": {
"includeFiles": ["email-templates/**"]
}
}
],
"routes": [
{
"src": "/lambdas/(.+)",
"dest": "/lambdas/$1.ts"
}
]
}
ê·žë ê² íë©Ž ë€ì곌 ê°ìŽ ížì¶í ì ììµëë€.
await ky.post(`${hostUrl}/lambdas/email?token=${someToken}`);
ë€ì API íìŽì§ ëŽë¶ìì ìŽë©ìŒì 볎ëŽê³ pug
ì ê°ì í
í늿 íìŒìì ìœë ê²ì ì²ëŠ¬íë lambdas/email.ts
íìŒìŽ ìë€ê³ ê°ì í©ëë€.
ëììŽ ëꞰ륌 ë°ëëë€.
ëí "includeFiles"ë @now/node
ììë§ ìëí©ëë€(ë€ë¥ž 겜ì°ìŒ ìë ìì§ë§ @now/next
ìë).
@BrunoBernardino ë node
íšì륌 ì¬ì©íë ê²ì²ëŒ 볎ìŽì§ë§ ìŽì ESMì ìœì ì ììµëë€!
ìŽê²ì mdx íìŽì§ 목ë¡ì ê°ì žì€ë €ê³ í ë ë°ìí©ëë€.
ìíž
import { NextApiRequest, NextApiResponse } from 'next'
import { promises as fs } from 'fs'
import { join } from 'path'
const { readdir } = fs
export default async (req: NextApiRequest, res: NextApiResponse) => {
const postFiles = await readdir(join(process.cwd(), 'pages', 'blog'))
const postNames: string[] = postFiles.filter((page: string) => page !== 'index.tsx')
const posts = []
for (const post of postNames) {
const mod = await import(`../pages/blog/${post}`)
posts.push({ ...mod, link: post.slice(0, post.indexOf('.')) })
}
res.status(200).json([])
}
ëŽê° ì»ë ì€ë¥ :
export const title = 'My new website!'
^^^^^^
SyntaxError: Unexpected token 'export'
@talentlessguy ì ë Zeit/Vercel íìŽ ìëëŒ ê·žì íë³µí ê³ ê°ì ëë€. íŽë¹ ì€ëí«ìì ëª ê°ì§ ì ì¬ì ìž ë¬žì 륌 볌 ì ììŒë¯ë¡ ê³ ê° ì§ìì ë ì í©í ì ììµëë€.
process.cwd()
ëì ì묎 ê²ë ì¬ì©íì§ ìê±°ë __dirname
륌 ì¬ì©í ì ììµëë€. ëë ëë€ìì íì륌 ì¬ì©íì§ ììì§ë§ ë€ë¥ž ê²ë€ì ì¬ì©íì§ ìììŒë¯ë¡ ê·žê²ìŽ 묞ì ìžì§ ìëì§ íì€íì§ ììµëë€.NextApiRequest
ë° NextApiResponse
륌 ì íìŒë¡ ê°ì žì€ê³ ìì§ë§ ìŽê²ì @now/node"
ìì ì€íëìŽìŒ í©ëë€. ë§ìµëê¹? ë°ëŒì ë€ì곌 ê°ìŽ ì íì ê°ì žììŒ í©ëë€.import { NowRequest, NowResponse } from '@now/node';
pages/...
ìì ê°ì žì€êž°/ìœêž° ì€ìŽì§ë§ includeFiles
륌 íµíŽ í¬íšíê³ ììµëê¹? ë¹ì ì now.json
ì(ë) ìŽë»ê² ì게ìµëê¹?@BrunoBernardino
__dirname
ë íì /
ìŽë¯ë¡ ì¬ì©í ì ììŒë©° ëì process.cwd()
ê° ì€ì 겜ë¡ë¥Œ 볎ì¬ì€ëë€.
ìì ì¬íì ìëœíê³ ìëíìµëë€.
ëë€/posts.ts
import { NowResponse, NowRequest } from '@now/node'
import { promises as fs } from 'fs'
import { join } from 'path'
const { readdir } = fs
export default async (req: NowRequest, res: NowResponse) => {
const postFiles = await readdir(join(process.cwd(), 'pages', 'blog'))
const postNames: string[] = postFiles.filter((page: string) => page !== 'index.tsx')
const posts = []
for (const post of postNames) {
const mod = await import(`../pages/blog/${post}`)
posts.push({ ...mod, link: post.slice(0, post.indexOf('.')) })
}
res.status(200).json([])
}
ì§êž.json
{
"builds": [
{
"src": "next.config.js",
"use": "@now/next"
},
{
"src": "lambdas/**/*.ts",
"use": "@now/node",
"config": {
"includeFiles": ["pages/blog/*.mdx"]
}
}
],
"routes": [
{
"src": "/lambdas/(.+)",
"dest": "/lambdas/$1.ts"
}
]
}
ëŽê° ì»ë ì€ë¥ :
import Meta from '../../components/Article/Meta.tsx'
^^^^^^
SyntaxError: Cannot use import statement outside a module
typescript ë
žë íšìê° .mdx
륌 몚ëë¡ ì·šêží ì ìë ê² ê°ìµëë€ :(
ìê² ìµëë€. 묞ì 륌 ì°Ÿì ê² ê°ìµëë€. ì§ì ê°ì žì€ë ëì íìŒ ëŽì©ì ìœê³ 구묞 ë¶ìíŽ ë³Žììì€. ëë ê·žë° ìì ì ê°ì žì€ë ê²ì 볞 ì ìŽ ììŒë©°, ìŒë° TS ëì ì¬ì©í ìë ìë ìŒë¶ Babel ë§ë²ììë§ ìëíë ê²ì²ëŒ 볎ì ëë€.
@BrunoBernardino ë¹ì ìŽ ì³ìì§ë§ íë²í ê²ìŽ ìëëë€ ... ëë ëìì esnextë¡ ì€ì íê³ ëªšëë esnextë¡ ì€ì íìµëë€. 몚ë ê²ì ê°ì žì¬ ì ììŽìŒíì§ë§ ìŽë»ê² ë ê·žë ì§ ììµëë€.
ìŽìšë 묞ì ì êŽë šìŽ ììŒë¯ë¡ ìŽëê°ì 구êžë§ í ê²ì ëë€.
ê±±ì ë§. ëª ê°ì§ íìŽ https://mdxjs.com/advanced/typescript ë° https://mdxjs.com/getting-started/webpack ì ìì ì ììŒë¯ë¡ @now/node
ë°°í¬ë¥Œ ë€ì곌 ê°ìŽ ì¡°ì íŽìŒ í©ëë€. ì¬ì©íŽ. ìŽìšë ê·žë€ì ì§ììŽ ëììŽ ëìŽìŒ í©ëë€.
ìŽê²ì ëí ìŽë€ ìì§ì? API 겜ë¡ìì ì¬ì©í html ìŽë©ìŒ í í늿ì í¬íší ì ìë€ë©Ž ì¢ì ê²ì ëë€. ì§êžì JS íìŒì í¬íšíê³ ìì§ë§ ìŽ íŽí¹ì í¹ë³í í¬ì ìëëë€.
ë ë€ë¥ž íŽí¹ì webpack raw-loader륌 ì¬ì©íì¬ jsì í¬íšìí€ë ê²ì ëë€.
yarn add --dev raw-loader
const templates = {
verify: require("raw-loader!../template/email/verify.hbs").default,
};
ê·žë° ë€ì templates.verify
륌 묞ììŽë¡ ì¬ì©í©ëë€.
ìŽê²ê³Œ êŽë šë ê²ìŒë¡ 볎ìŽë next-i18next ì 묞ì ê° ììµëë€( vercel/vercel#4271 ). Ʞ볞ì ìŒë¡ now
ë /public/static/locales/
ìì ìë .json
íìŒì ìë²ëŠ¬ì€ íšìì ë£ì§ ììµëë€. ì¬êž°ì ë
Œìë êž°ë¥ìŽ ë€ìì ì¶ê°ë ëê¹ì§ ë구ë ì§ íŽê²° ë°©ë²ì ì ê³µí ì ììµëê¹?
@borispoehland ììì ê°ì žì€êž°/ì구 íŽê²° ë°©ë²ì ìëíìµëê¹? ìëíŽìŒ í©ëë€.
@borispoehland ììì ê°ì žì€êž°/ì구 íŽê²° ë°©ë²ì ìëíìµëê¹? ìëíŽìŒ í©ëë€.
@BrunoBernardino ì íí ìê²¬ìŽ ë¬Žìì ì믞íëì§ ëªšë¥Žê² ìµëë€.
public/static/locales
ì ìë 몚ë .json
íìŒì ìŽë»ê²ë ìë²ëŠ¬ì€ íšìë¡ ê°ì žì€ë ì륌 ë€ìŽ 죌ìê² ìµëê¹? ê·žëŠ¬ê³ ìŽê²ì ìŽë ìì(ìŽë€ íìŒìì) í©ëê¹?
ëë ë€ìì ì¬ì©íê³ ììµëë€ (ìŽì ì ìžêžíë¯ìŽ includeFiles
ë @now/next
ì ížíëì§ ììµëë€. ìŽê²ìŽ ëŽ ë¬žì ì ìí¥ì 믞ì¹ë ê²œì° idk).
ê²ë€ê°, next-i18next
ë ëìê² ìŒì¢
ì ëžëë°ì€ìŽêž° ë묞ì(ë°ëŒì ê±°êž°ìì íìŒì ê°ì žì€ê³ ì¶ì§ ìì) next-i18next
ê° ì§ì ì¡ìžì€íììì€(ìì ë€ë¥ž 죌ììì PROJECT_DIRNAME
next.config.json
ëŽë¶ì ì ìëìŽ ê°ì žì€êž°ë¥Œ ìëìŒë¡ ìííŽìŒ íìµëë€. ìŽê²ì ì ê° ëë¬íë €ê³ íë ê²ìŽ ìëëë€). vercel/vercel#4271 ììì²ëŒ , ì ë now
ê° ì .json
íìŒì ìŽë»ê²ë ìë²ëŠ¬ì€ êž°ë¥ìŒë¡ ê°ì žì€êž°ë¥Œ ìí©ëë€.
@borispoehland ëŽë¶ _any_ íìŒì pages/api
(ëë ê·ž ì€ íëê° ížì¶ë©ëë€) ê°ì ê²ì í https://github.com/vercel/next.js/issues/8251#issuecomment -544008976
ê°ì žì€êž°ì ëíŽ ì묎 ìì ë ìíí íìê° ììµëë€. ìì ì webpack vercelìŽ ì€íëë©Ž íŽë¹ íìŒìŽ í¬íšëìŽìŒ íê³ ìëíŽìŒ íë€ë ê²ì ì ì ìë€ë ê²ì ëë€.
ëë ê·žê²ìŽ ìë¯žê° ìꞰ륌 ë°ëëë€.
@borispoehland ëŽë¶ _any_ íìŒì
pages/api
(ëë ê·ž ì€ íëê° ížì¶ë©ëë€) ê°ì ê²ì í # 8251 (ìœë©íž)ê°ì žì€êž°ì ëíŽ ì묎 ìì ë ìíí íìê° ììµëë€. ìì ì webpack vercelìŽ ì€íëë©Ž íŽë¹ íìŒìŽ í¬íšëìŽìŒ íê³ ìëíŽìŒ íë€ë ê²ì ì ì ìë€ë ê²ì ëë€.
ëë ê·žê²ìŽ ìë¯žê° ìꞰ륌 ë°ëëë€.
@BrunoBernardino ìŽ ì ê·Œ ë°©ìì 묞ì ë json íìŒìŽ now
: "ìŽëŽ, ê·ž ëë í 늬 ìì 몚ë json íìŒì ì¬ê·ì ìŒë¡ ì ííëŒ"ëŒê³ ë§íë ë ì¬ìŽ ë°©ë²ìŽ ììµëê¹? 믞늬 ê°ì¬ë늜ëë€
ížì§: json
íìŒì ìëìŒë¡ ê°ì žì€ëëŒë ìŽì 곌 ëìŒí ì€ë¥ê° ë°ìí©ëë€. ëë ìŽê²ì ìíŽ ìë¡ìŽ 묞ì 륌 ìŽ ââê²ì
ëë€.
ëêµ°ê°ê° í ë¡ ì ì°žì¬íë ë° êŽì¬ìŽ ìë 겜ì°ë¥Œ ëë¹ íì¬ ëŽ ë¬žì ì ëí ì 묞ì 륌 ìŽììµëë€ . ì§êž ê°ì¬í©ëë€, @BrunoBernardino !
__dirname
륌 ì ìì ìŒë¡ ìëí ê²ìŒë¡ ììíë ëë¡ ì¬ì©í ì ìëë¡ íë ë ë€ë¥ž ìµì
/íŽê²° ë°©ë²ì webpack 구ì±ì ì¡°ì íë ê²ì
ëë€.
Ʞ볞ì ìŒë¡ webpackì ë€ì곌 ê°ìŽ ì§ìíì§ ìë í íŽëŠ¬íì ì¬ì©íì¬ ë€ìí ë
žë ì ìì ë³ì¹ì ì§ì í©ëë€.
https://webpack.js.org/configuration/node/
ê·žëŠ¬ê³ webpack Ʞ볞 ì€ì ì __dirname
ë° __filename
ê·žëë¡ ëë ê²ì
ëë€. ìŠ, íŽëŠ¬ííì§ ìê³ ë
žëê° ì ìì ìŒë¡ ì²ëŠ¬íëë¡ í©ëë€.
ê·žë¬ë, Next.jsì ì¹í© ì€ì ì / ì¬ì© ì¹í© Ʞ볞ê°ì ë°ìíì§ ììµëë€ https://github.com/vercel/next.js/blob/bb6ae2648ddfb65a810edf6ff90a86201d52320c/packages/next/build/webpack-config.ts#L661 -L663
ê·ž 몚ë ê²ì ì¹í© 구ì±ì ì¡°ì íêž° ìíŽ ìëì ì¬ì©ì ì ì Next êµ¬ì± íë¬ê·žìžì ì¬ì©íìµëë€.
ì€ì: ìŽê²ì ì ì¬ì© ì¬ë¡ìì ìëí©ëë€. êŽë²ìí í겜/구ì±ìì í ì€ížëì§ ìììŒë©° 몚ë Next.js ëšì/íµí© í ì€ížì ëíŽ í ì€ížëì§ ìììµëë€. ê·žê²ì ì¬ì©íë©Ž í겜ì ìëíì§ ìì ë¶ìì©ìŽ ìì ì ììµëë€.
ëí Nextë__dirname
ë°__filename
ëí ì¹í© Ʞ볞 ì€ì ì ì¬ì©íì§ ìë í¹ì í ìŽì ê° ìì ì ììµëë€. ë°ëŒì ìë ìœëìë ìëíì§ ìì ë¶ìì©ìŽ ìì ì ììŒë¯ë¡ 죌ìíŽì ì¬ì©íŽìŒ í©ëë€.
ëí ìë íë¬ê·žìžì next-compose-plugins
íší€ì§ì íšê» ì¬ì©íëë¡ ì€ê³ëììµëë€. https://github.com/cyrilwanner/next-compose-plugins
ê·žë¬ë ìŒë° íë¬ê·žìžìŒë¡ë ìëíŽìŒ í©ëë€. https://nextjs.org/docs/api-reference/next.config.js/custom-webpack-config
const withCustomWebpack = (nextCfg) => {
return Object.assign({}, nextCfg, {
webpack(webpackConfig, options) {
// We only want to change the `server` webpack config.
if (options.isServer) {
// set `__dirname: false` and/or `__filename: false` here to align with webpack defaults:
// https://webpack.js.org/configuration/node/
Object.assign(webpackConfig.node, { __dirname: false });
}
if (typeof nextCfg.webpack === 'function') {
return nextCfg.webpack(webpackConfig, options);
}
return webpackConfig;
},
});
};
@jkjustjoshingìŒë¡ ì룚ì ì 구í
ë€ì ì€ë¥ê° ë°ìí©ëë€.
Error: GraphQL error: ENOENT: no such file or directory, open '/vercel/37166432/public/ts-data.csv'
ëŽ ìœë:
const content = await fs.readFile(
path.join(serverRuntimeConfig.PROJECT_ROOT, "./public/ts-data.csv")
);
íìŒì ëí ë§í¬ë ë€ì곌 ê°ìµëë€. https://github.com/bengrunfeld/trend-viewer/blob/master/pages/api/graphql-data.js
@bengrunfeld ì, ê·íì ì룚ì ì ë¡ì»¬ììë§ ìëí©ëë€.
ìµê·Œì ë¹ì·í 묞ì ê° ììê³ (API 겜ë¡ìì íìŒì ìœê³ ì¶ìì) ì룚ì ìŽ ììë³Žë€ ì¬ì ìµëë€.
path.resolve('./public/ts-data.csv')
ìë
@borispoehland ì ë§ ê°ì¬í©ëë€!! ê·íì ì룚ì ì íë¥íê² ìëíìµëë€!
@bengrunfeld 묞ì ììµëë€. ì ë ì°ì°í ë°ê²¬íìµëë€( @BrunoBernardino ;)). ì¬êž° ìë 몚ë ì¬ëì 묞ì ì ëí íŽê²°ì± ìŽëŒê³ ìê°í©ëë€.
ì¬ì í next.config.js
륌 ì€ì íŽìŒ í©ëë€. @borispoehland ì ì룚ì
ìŽ ìëíë ê²ì ë³Žê³ íìŒì ìì íëë° ë¹ì·í ì€ë¥ê° ë°ìíìµëë€.
ê·žë° ë€ì ìì @jkjustjoshing ì룚ì ìŒë¡ ì¬ì€ì íê³
# next.config.js
module.exports = {
serverRuntimeConfig: {
PROJECT_ROOT: __dirname
}
}
ì¬ì í
next.config.js
륌 ì€ì íŽìŒ í©ëë€. @borispoehland ì ì룚ì ìŽ ìëíë ê²ì ë³Žê³ ì ê±°íëë° ë¹ì·í ì€ë¥ê° ë°ìíìµëë€.ìì @jkjustjoshing ì룚ì ìŒë¡ ì¬ì€ì íê³
# next.config.js module.exports = { serverRuntimeConfig: { PROJECT_ROOT: __dirname } }
@bengrunfeld ì ë§? ìœëì ë€ë¥ž ì§ì ìì ì¬ì í PROJECT_ROOT
ì ê·Œ ë°©ìì ì¬ì©íê³ ìì ì ììµëë€. ëŽ íë¡ì ížììë ìŽ ì ê·Œ ë°©ì ììŽ ìëíêž° ë묞ì
ëë€. ì€ë¥ê° ìŽë»ê² ì게ìµëê¹?
Vercelì ë°°í¬í ë SSG ë° SSR/믞늬 볎Ʞ 몚ëìì 몚ë ìëíë íìŽì§ì readFile
륌 ìì±íë €ë©Ž ìŽë»ê² íŽìŒ í©ëê¹?
ìë íì§ ìë ë°ëªš ì ì¥ì: https://github.com/mathdroid/blog-fs-demo
@mathdroid getStaticProps
ë° getStaticPaths
íšì ëŽìì readFile
ë° readdir
ê°ê° ìŽëíŽ ë³Žììì€. ê·žë ì§ ììŒë©Ž ìœëê° ëžëŒì°ì ìì ì€íë ì ììµëë€.
ê·žë¬ë fs
ê°ì žì€ë ê²ì ì ììŽìŽìŒ í©ëë€.
ê·žê²ìŽ ìŽë»ê² ìëíëì§ ìë €ì£Œììì€.
@borispoehland ë©ì§ ì룚ì
ì ê°ì¬ë늜ëë€. path.resolve()
~ /public
ê° ë¡ì»¬ê³Œ Vercelìì 몚ë ìëí ê²ìŽëŒê³ ììíì§ ëª»íìµëë€. ë¹ì ì ì€ëì ëŽ êµ¬ìžì£Œì
ëë€. :+1:
@borispoehland ìë²ëŠ¬ì€ êž°ë¥ ëŽìì ì룚ì
ì ìëíì§ë§ ì¬ì í ë€ìì ì»ìµëë€.
ENOENT: íŽë¹ íìŒìŽë ëë í°ëŠ¬ê° ììµëë€. '/var/task/public/posts.json'ì ìœëë€.
const postsFile = resolve('./public/posts.json');
const updateCache = async (posts: IPost[]): Promise<IPost[]> => {
postCache = posts;
fs.writeFileSync(postsFile, JSON.stringify(postCache)); // <====
return postCache;
}
ëë next.config.js ììŽ ì°ëŠ¬ì íšê» ìëíë€.
module.exports = {
serverRuntimeConfig: {
PROJECT_ROOT: __dirname
}
}
ì룚ì ìŽ ìë²ëŠ¬ì€ êž°ë¥ìì ìëíì§ ìì ì ììµëê¹?
@borispoehland ìë²ëŠ¬ì€ êž°ë¥ ëŽìì ì룚ì ì ìëíì§ë§ ì¬ì í ë€ìì ì»ìµëë€.
ENOENT: íŽë¹ íìŒìŽë ëë í°ëŠ¬ê° ììµëë€. '/var/task/public/posts.json'ì ìœëë€.const postsFile = resolve('./public/posts.json'); const updateCache = async (posts: IPost[]): Promise<IPost[]> => { postCache = posts; fs.writeFileSync(postsFile, JSON.stringify(postCache)); // <==== return postCache; }
ëë next.config.js ììŽ ì°ëŠ¬ì íšê» ìëíë€.
module.exports = { serverRuntimeConfig: { PROJECT_ROOT: __dirname } }
ì룚ì ìŽ ìë²ëŠ¬ì€ êž°ë¥ìì ìëíì§ ìì ì ììµëê¹?
ëë ê·žê²ìŽ ë¹ì ì ëìì ìëíì§ ìë ìŽì 륌 ëªšë¥Žê² ìµëë€ ... ì£ì¡í©ëë€
ì¢ì, @bengrunfeld ìœë륌 ì¬ì©íì¬ ìœêž° ìì
ì ìííì§ë§ ë¶ííë ë€ì곌 ê°ìŽ ìì±í ì ììµëë€.
[ì€ë¥: EROFS: ìœêž° ì ì© íìŒ ìì€í
, '/var/task/public/posts.json' ìŽêž°]
ë°ëŒì ë묎 ë§ì ë°ìŽí°ë² ìŽì€ ížì¶ì íŒíêž° ìíŽ ìºì륌 ì
ë°ìŽíží ë°©ë²ìŽ ììµëë€.
@neckaros .json
ìŽìžì íìŒ(ì: .jpg
íìŒ)ì ìœêž° ìíŽ ì ì ê·Œ ë°©ìì ì¬ì©íŽ 볎ì
šìµëê¹ ?
ì¢ì, @bengrunfeld ìœë륌 ì¬ì©íì¬ ìœêž° ìì ì ìííì§ë§ ë¶ííë ë€ì곌 ê°ìŽ ìì±í ì ììµëë€.
[ì€ë¥: EROFS: ìœêž° ì ì© íìŒ ìì€í , '/var/task/public/posts.json' ìŽêž°]
ë°ëŒì ë묎 ë§ì ë°ìŽí°ë² ìŽì€ ížì¶ì íŒíêž° ìíŽ ìºì륌 ì ë°ìŽíží ë°©ë²ìŽ ììµëë€.
@neckaros S3(ëë ë€ë¥ž ìžë¶ íìŒ ìì€í )ìì ì°ê³ ìœì ì ììŽìŒ íì§ë§ ì ë ìŒë°ì ìŒë¡ íë°ì±ìŽ ìì ì ìë ë¹ ë¥Žê³ ìºìë í목ì redis륌 ì¬ì©í©ëë€. https://redislabs.comì "ìë²ëŠ¬ì€"ë¡ ì ì§íê³ ììŒë©° ìíë ê²œì° https://nextjs-boilerplates.brn.shì íë¡ëì ì€ë¹ ìœë ìì ê°
@borispoehland ëë ìëžëŠ¬ì€ êž°ë¥ìì ìœì ìë ìì§ë§ ìž ìë ììµëë€. ê·žë¬ë ì ìœí ìž ë¥Œ ì¶ê°íë ëì ìŠë¶ ë¹ë(ì¬ê²ìŠ)ìì ìºì륌 ìë¡ ê³ ì³ ìëíê² íìµëë€. ëìì§ ìì íšíŽìŽëŒê³ ìê°í©ëë€. ë¹ì ì ëìì 죌ì ì ê°ì¬í©ëë€!
@BrunoBernardino ê°ì¬í©ëë€. ìŽíŽë³Žê² ìµëë€. ëª ëª ì ì¬ì©ìê° ììŽë 깚ì§ì§ ìë ìì ë¬Žë£ ì·šë¯ž ì룚ì ì ì°Ÿê³ ììµëë€. :)
ëª ëª ì ì¬ì©ìê° ììŽë 깚ì§ì§ ìë ìì ë¬Žë£ ì·šë¯ž ì룚ì ì ì°Ÿê³ ììµëë€. :)
ììë€. RedisLabsì VercelìŽ ì 륌 ìíŽ ê·žë ê² íìµëë€. ð¯
íêž° í íì¥ os íší€ì§ë¡ ìì íë íìŒì ìì±íìµëë€ ...
import { tmpdir } from "os";
const doc = new PDFDocument()
const pdfPath = path.join(tmpdir(), `${store.id}${moment().format('YYYYMMDD')}.pdf`)
const writeStream = doc.pipe(fs.createWriteStream(pdfPath)
íìŒ ìœêž°ë @subwaymatch ì룚ì
곌 íšê» ìëí©ëë€.
const logoPath = path.resolve('./public/logo.png')
íêž° í íì¥ os íší€ì§ë¡ ìì íë íìŒì ìì±íìµëë€ ...
import { tmpdir } from "os"; const doc = new PDFDocument() const pdfPath = path.join(tmpdir(), `${store.id}${moment().format('YYYYMMDD')}.pdf`) const writeStream = doc.pipe(fs.createWriteStream(pdfPath)
íìŒ ìœêž°ë @subwaymatch ì룚ì 곌 íšê» ìëí©ëë€.
const logoPath = path.resolve('./public/logo.png')
ì¢ìµëë€. ìŽ íìŒì ëŽì©ì ë€ì ìœì ì ììµëê¹? ëë í ëŠ¬ê° ì¡ìžì€ ê°ë¥íê³ ì구ì ì ëê¹?
@marklundin tmpdir
ëŒë ìŽëŠì íšì륌 ì¬ì©íë©Ž ì구ì ìžì§ ìì¬ëì§ë§ ìŽê²ìŽ ìëíë©Ž ì€ì ë¡ tmpdir
ê° ì€ì ë¡ ìŒë§ë ìŒìì ìžì§ ìë ê²ìŽ ì¢ìµëë€. ì... ð€
ìŽì ëí ì ë°ìŽížê° ììµëê¹? getInitialPropsììë ìëíì§ë§ API 겜ë¡ììë ìëíì§ ìë ìŽì ê° ê¶êží©ëë€ ð€·ââïž
ëŽ íì¬ íŽê²° ë°©ë²
const data = await import(`../../../../data/de/my-nice-file.json`);
res.json(data.default);
íì¬ API 겜ë¡ììë ìŽ ë¬žì ê° ììµëë€.
íì¬ API 겜ë¡ììë ìŽ ë¬žì ê° ììµëë€.
ì¬êž°ì ëª ê°ì§ íšê³Œì ìž ì룚ì ìŽ ììµëë€. 구첎ì ìŒë¡ ìŽë€ 묞ì ê° ììµëê¹?
ìŽ ì€ë ëì ì ììë ë¶êµ¬íê³ ìŽ ìì ì ìííë ë° ìŽë €ìì ê²ªê³ ììµëë€. ëŽ ì¬ì© ì¬ë¡ë ê°ìŽë륌 ìì± ì€ìŽë©° êµ¬ì± ìì ì첎ì íšê» êµ¬ì± ììì ìì€ ìœë륌 íìíë €ë ê²ì ëë€. ìŽ ìì ì ìííë ë°©ë²ì fs륌 ì¬ì©íì¬ getServerSideProps ëŽë¶ì êµ¬ì± ììì jsx íìŒì ë¡ëíê³ íìŒ ëŽì©ì 묞ììŽ ê°ì ìíìŒë¡ ì ë¬íë ê²ì ëë€.
ë¡ì»¬ìì ìëíë ê²ì ëíŽ êž°ë¶ìŽ ìŽìíì§ë§ ë°°í¬íë €ê³ íì ë êž°ìšìŽ ì¬ëŒì¡ìµëë€.:(
ì°žì¡°: https://github.com/ElGoorf/i18next-guide/blob/fix-example-components/pages/plurals.jsx
@ElGoorf 묞ì ë public
íìŒìŽ ê°ì¥ì늬ì ìê³ êž°ë¥ìŽ ëë€ì ìë€ë ê²ì
ëë€. ìŽì @vercel/next
ì¬ì í includeFiles
íì©íì§ ììŒë¯ë¡ ìëìí€ë ê°ì¥ ì¬ìŽ ë°©ë²ì lambda
íšì륌 íšê» ì¬ì©íë ê²ì
ëë€.
ì¬êž°ì ë€ë¥ž ì¬ëë€ì ëìŽ ìí ìœëê° ììµëë€. https://github.com/vercel/next.js/issues/8251#issuecomment -614220305
@BrunoBernardino ê°ì¬í©ëë€. "x ìšê²šì§ íëª©ìŽ ë ë§ìŽ ë¡ëë©ëë€..."륌 ëì¹ ì€
ë¶ííë Edge/Lambdaì ëíŽ ì²ì ë€ìêž° ë묞ì ê·íì ì룚ì ì ìŽë €ìì 겪ìì§ë§ @balthild ì ì룚ì ìŽ node.fs ë°©ë²ì ìëíêž° ì ì ìë ì¶êµ¬íë ê²ì ë ê°ê¹ë€ë ê²ì ìììµëë€. https:// /github.com/vercel/next.js/issues/8251#issuecomment -634829189
ìì²ë! ìëìí€ì šëì? ìëë©Ž ì¬ì í 묞ì ê° ììµëê¹?
VercelìŽ íŽë¹ ì©ìŽë¥Œ ì¬ì©íëì§ íì€íì§ ìì§ë§ Edgeë ì ì íìŒìŽ ì ê³µëë CDNì ì믞íê³ ëë€ë AWS Lambda íšìì²ëŒ 격늬ë API 겜ë¡ìì ížì¶ëë "ë°±ìë" íšì륌 ì믞í©ëë€. .
ìŽëŽ,
vercelìì next.js륌 ì¬ì©íì¬ íìŒ ì°êž°ì ëí ì
ë°ìŽížê° ììµëê¹? 묞ì ììŽ ìœì ì ììµëë€. const logoPath = path.resolve('./public/logo.png')
public/sitemap.xml íìŒì ë®ìŽì°ë €ê³ í©ëë€(vercelì í¬êž° ì íìŒë¡ ìžíŽ). ì€ë¥ ììŽ ê³µì© íŽëì ì ì íìŒë¡ë§ ë°íí ì ììµëë€. ìŽì ì zlibë¡ ì¬ìŽížë§µì 구ííê³ ìëµì ì€ížëŠ¬ë°íì§ë§ ì€ížëŠŒìŽ ìë£ë ëê¹ì§ êž°ë€ë žë€ê° ë°ííë ê² ê°ìµëë€. ìŽê²ì í¬êž° ì í ì€ë¥ì ëë¬íì§ ìì§ë§ ë¶ííë ë§€ì° ë늜ëë€. ëë ì¬ëë€ìŽ ê°ì§ ì ìë 몚ë ì ìì ìŽë € ììµëë€. ì¬ìŽížë§µì API ížì¶ìì ë³ëì ë°±ìëë¡ ë¹ëëë©° ì êž°ì ìŒë¡ ì ë°ìŽížíŽìŒ í©ëë€.
ëŽê° ìëí ê²ë€ :
@emomooney , ì ë VercelìŽ íšìì íìŒì ì°ë ê²ì íì©íì§ ìëë€ê³ ìê°í©ëë€(ìºì±ì 겜ì°ìë), ìëíë©Ž ìë²ëŠ¬ì€ì 죌ì "ì¥ì "ì ìí ë¹ì ì¥ ìíìŽêž° ë묞ì ìíê° ì¶ê°ë ê²ìŽêž° ë묞ì ëë€. edge/cdnì ì¬ì©íŽìŒ í©ëë€.
ìŽì ì zlibë¡ ì¬ìŽížë§µì 구ííê³ ìëµì ì€ížëŠ¬ë°íì§ë§ ì€ížëŠŒìŽ ìë£ë ëê¹ì§ êž°ë€ë žë€ê° ë°ííë ê² ê°ìµëë€.
íì ížì¶ì ëíŽ ìŽë¬í ë늌ì 겜íí ê²ìžì§ ìëë©Ž ìœë ì€íížì ëíŽ ì²« ë²ì§ž ížì¶ì ëí ìë ì íê° ë°ìí ê²ìžì§ ê¶êží©ëë€. ëë ìŽê²ìŽ ëŽê° ì¬êž°ìì íë ê²ê³Œ ì ì¬í next.js API íšì ëë ì ì© ëë€ë¥Œ íµí Vercelì ëí API ížì¶ìŽëŒê³ ììí©ëë€.
ê·žë ë€ë©Ž ì¬ì í ë묎 ë늬ë€ë©Ž "ë³ëì ë°±ìë"ê° Vercel ìžë¶ì ììµëê¹? ê·žë ë€ë©Ž ì ì¬ì ìŒë¡ ìŽ íìŒì ì¬ì©íì¬ sitemap.xml
íìŒì ë§ë€ê³ vercel --prod
ëë©ìžì íìŒì "ìºì±"íì¬ ìœê³ ì¡ìžì€í ì ììŒë©° ì
ë°ìŽížíêž°ë§ íë©Ž ë©ëë€. robots.txt
륌 ì¬ì©íì¬ ì¬ìŽížë§µì ë€ë¥ž ëë©ìž/íì ëë©ìžì ì°ê²°í©ëë€.
ê°ì¥ ì ì©í ëêž
ëŽê° ì¬ì©íë íŽê²° ë°©ë²:
겜ë¡ê° íìí ìì¹ì
ìŽê²ìŽ íì¬ íìŒì ìëì ìž ê²œë¡ê° ìë ì°žì¡° íìŒì íìì±ì íŽê²°íì§ ëª»íë€ë ê²ì ìê³ ìì§ë§ ìŽê²ì ëŽ ë§€ì° êŽë šë ì¬ì© ì¬ë¡(
/public/images
íŽëìì ìŽë¯žì§ íìŒ ìœêž°)륌 íŽê²°í©ëë€.