์ด์ ์ฐ๋ฆฌ ์ค ์ผ๋ถ๋ ES2015๋ก ์์ฑ๋ NPM ํจํค์ง(ํนํ ๊ตฌ์ฑ ์์)๋ฅผ ํธ๋์คํ์ผํ์ง ์๊ณ ๋ฐฐ์กํฉ๋๋ค.
ํนํ Next.js ๋๋ CRA(ํธ๋์คํ์ผ์ ์ํํ๋)์ ๊ฐ์ ํ๋ก์ ํธ์์ ์ฌ์ฉํ๋ ค๋ ๊ฒฝ์ฐ์๋ ๋งค์ฐ ์ข์ต๋๋ค. ๋ค์๊ณผ ๊ฐ์ ํํ์ ์ ๊ณตํฉ๋๋ค.
๊ทธ๋ฌ๋ ์ด์ ์ฐ๋ฆฌ๋ ์ด๊ฒ์ ํ ์ ์์ต๋๋ค. node_modules ๋ด๋ถ์ ๋ชจ๋ ๊ฒ์ babel ๋ณํ์์ ์ ์ธ ํฉ๋๋ค.
์ ์๋ ์๋ฃจ์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
babel์ ๊ฑฐ์ณ์ผ ํ๋ ๋ชจ๋์ ํฌํจํ๊ธฐ ์ํด next.config.js
์ ํญ๋ชฉ์ด ์์ต๋๋ค. ๋ณด๋ค:
module.exports = {
transpileModules: [
"my-component",
"redux/src"
]
}
webpack()
ํ์ฅ์ผ๋ก ์ด๊ฒ์ด ๋ถ๊ฐ๋ฅํ ์ด์ ๋ ๋ฌด์์
๋๊น?transpileModules
๋ ๋์ ์๋ฆฌwebpack() ํ์ฅ์ผ๋ก ์ด๊ฒ์ด ๊ฐ๋ฅํ์ง ์์ ์ด์ ๋ ๋ฌด์์ ๋๊น?
๋๋ ๋น์ ์ด ์ฌ์ฉ์ ์ ์ webpack ๊ตฌ์ฑ์ ์๋ฏธํ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. ๊ฐ๋ฅํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ด๊ฒ์ ๊ธฐ์กด ๋ก๋์ ์์ต๋๋ค. ๊ทธ๊ฒ์ ์ป๋ ๊ฒ์ ๋ค์ ์ด๋ ต์ต๋๋ค.
transpileModules
๋ ์ ๋ค๋ฆผ
์์ฒญ๋. ์ ๋ฐ์ดํธํ๊ฒ ์ต๋๋ค.
์ ๊ท ํํ์์ ์๋ฝํ ๊น์?
๋ค. ํ์คํ.
์ด๋ด,
๋ด ์น์ฌ์ดํธ๋ฅผ ์์ํ๋ฉด์ Lerna/Next/Styled์ ๊ฐ์ ์๋ก์ด ๊ธฐ์ ์ ์๋ํ๊ณ ์์ผ๋ฉฐ ์ด์ ๋ํ ์ด๊ธฐ ํผ๋๋ฐฑ์ ๊ธฐ๊บผ์ด ์ ๊ณตํ๊ฒ ์ต๋๋ค.
๋ด NextJs ๋ชจ๋์์ CRA ๊ธฐ๋ฐ ๋ชจ๋์ ๊ฐ์ ธ์ค๊ฑฐ๋ ๋ณํํ๋ ค๊ณ ์๋ํ์ง๋ง ๋ณํ์ ์ํํ๋ ๋ฐฉ๋ฒ์ ๋ชฐ๋๋ ์ค๋ณต ๋ฌธ์ ๋ฅผ ์ด์์ต๋๋ค(๋ด ๋ชจ๋์ ๋ ๋ฆฝ ์คํํ์ผ๋ก ์คํ ๊ฐ๋ฅํ๊ฒ ์ ์งํ๊ณ ์ถ์ต๋๋ค).
๋๋ ๋ํ Lerna๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ Babel์ด ๊ฐ ๋ชจ๋์ ๋ ธ์ถํ๊ธฐ ์ ์ ํธ๋์คํ์ผํ๊ณ ์๋ค๋ ๊ฒ์ ์์์ฐจ ๋ ธ์ง๋ง @arunoda๊ฐ ์ ์ํ ๋๋ก ํ๊ณ ํด๋ผ์ด์ธํธ ์ฑ์ด ํธ๋์คํ์ผ์ ํ๋๋ก ํ๋ ๊ฒ์ด ๋ ๋์ ๊ฒ ๊ฐ์ต๋๋ค.
๋ด ํด๋ผ์ด์ธํธ์ ๋ํ ๋จ์ผ babel ๊ตฌ์ฑ์ ๊ฐ๊ณ ํด๋น ๊ตฌ์ฑ์ ๋ถ๋ฆฌ๋ ๋ชจ๋ ๋ชจ๋๊ณผ ๊ณต์ ํ๊ณ ์ถ์ต๋๋ค. ๋ค์ ๋ฌ๋ ์ธ๋ถ์์ ๋ด ๋ชจ๋์ ๋ ๋ฆฝ ์คํํ์ผ๋ก ์คํํ ์ ์๋ ๊ธฐ๋ฅ์ ์ ์งํ๋ ค๋ ๊ฒฝ์ฐ ์๋ง๋ ๊ทธ๋ ๊ฒ ์ฝ์ง ์์ ๊ฒ์ ๋๋ค.
๋ด ํ์ฌ ํ ์คํธ ํ๋ก์ ํธ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. https://github.com/slorber/playground/ ํฌํฌ/PR์ด ์๋ ์ฆ์ ์ ๊ทธ๋ ์ด๋๋ฅผ ์๋ํ๊ฒ ์ต๋๋ค. @arunoda ์์
@slorber๋ ํ์ฌ 2.0 ๋ฆด๋ฆฌ์ค์ ์ง์คํ๊ณ ์์ผ๋ฉฐ ๊ฐ๋ฅํ ํ ๋ฏธ์ธ ์กฐ์ ํ๊ณ ๋ฒ๊ทธ๋ฅผ ์ฐพ์ต๋๋ค.
๋๋ ์ด๊ฒ์ ๋ํ ์์ ์ ์์ํ์ง ์์์ง๋ง 2.0 ์ดํ์ ์ด๊ฒ์ ํ ์ ์์ต๋๋ค.
์ข์, ๊ทธ๋์ ๋ด๊ฐ ํฌํฌ๋ฅผ ๋ง๋ค๊ฑฐ์ผ. ์ค์ํ ์น ์ฌ์ดํธ๋ฅผ ๊ตฌ์ถํ์ง ์๊ณ ์๊ณ webpack 1.13์ด jsnext:main/module ํ๋๋ฅผ ํด๊ฒฐํ์ง ์๋๋ค๊ณ ์๊ฐํ๊ธฐ ๋๋ฌธ์ ์ด๋ฏธ 2.0.0 ๋ฒ ํ์ ๋ํด ์คํ ์ค์ ๋๋ค.
๋๋ ๋ฒ๋ค๋ฌ ์ ๋ฌธ๊ฐ๋ ์๋์ง๋ง package.json์ "๋ชจ๋" ํ๋๋ฅผ ์ฌ์ฉํ๊ณ ์ถ์ต๋๋ค. ์๋์? "main"์ ๋ด๊ฐ ์๋ ํ ์ด๋ฏธ ํธ๋์คํ์ผ๋ ์ฝ๋์ธ ๊ฒ ๊ฐ์ต๋๋ค. ๊ทธ๋ฌ๋ webpack ๊ตฌ์ฑ์์ ํธ๋์คํ๋ ์ด์ ์ ํฌํจ/์ ์ธํ ์ ์์ผ๋ฏ๋ก ๊ด๋ จ์ฑ์ด ์๋์ง ํ์คํ์ง ์์ต๋๋ค. 3๊ฐ์ง ํ๋ ์ค ์ด๋ ๊ฒ์ ์ฌ์ฉํ๊ณ ์ถ์์ง ์ถ์ฒํด ์ฃผ์ธ์.
@slorber webpack ์ NPM์ฒ๋ผ main
๋ง ์ง์ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋น์ ์ ๊ทธ๊ฒ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
next.conf.js
์ exclude
ํจ์์์ ํ์ผ ๊ฒฝ๋ก๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
ํ , ๋ด๊ฐ ์ค์ ๋ก Next 2.x์ ๋ํด ๋ณธ ๊ฒ์ ๋ฐ๋ฅด๋ฉด jsnext:main ์ด ์๋ํ์ง ์๋ ๋์(๋ด๊ฐ ๊ธฐ์ตํ๋ ํ) ๋ชจ๋์ด ์๋ํ๋ ๊ฒ์ ๋ณด์์ง๋ง(๊ทธ๋ฌ๋ ๋์ค์ ๋ณํ๋์ง ์์๊ธฐ ๋๋ฌธ์ ๋ฐํ์์ ์คํจํ์ต๋๋ค.) ํ์ง๋ง ์ง์ ํด์ผ ํฉ๋๋ค.
์ด์จ๋ jsnext:main ๋๋ module์ ์ด ๋ฌธ์ ์ ๋ํ ํด๊ฒฐ์ฑ ์ด ์๋ ๊ฒ ๊ฐ์ผ๋ฏ๋ก ํ์ฌ ๋ด๋ถ ๋ชจ๋์ ๊ฒฝ์ฐ ๋ณํ์ ํ์ฑํํ๋ ๊ฒ๋ง์ผ๋ก๋ ์ถฉ๋ถํ ๊ฒ์ ๋๋ค.
์ปค๋ฎค๋ํฐ๊ฐ ํ๋์ ์ ๊ทผ ๋ฐฉ์์ ๋์ํ์ง ์์์ต๋๊น? ์๋ฅผ ๋ค์ด, react-youtube
๋ค๋ฅธ ํ๋๋ฅผ ๋ฌธ์ ์์ด ์ฌ์ฉํ ์ ์์์ต๋๋ค. ๊ฒ์ํ๊ธฐ ์ ์ ๋ง์ ์์ ๋ชจ๋์ด ๋ณํ๋๋ค๊ณ ๊ฐ์ ํ๊ณ ์์ต๋๊น?
์ฐธ์กฐ: https://github.com/rauchg/blog/blob/master/components/post/youtube.js
๋ค, ๋๊ฐ/์ด๋ป๊ฒ ๋ชจ๋์ด ์๋น๋ ์ง ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์ ๊ฒ์ํ๊ธฐ ์ ์ ํญ์ ํธ๋์คํ์ผํ๋ ๊ฒ์ด ํฉ๋ฆฌ์ ์ ๋๋ค. ์ด๊ฒ์ด Rollup์ด ์ ์ํ๋ ๊ฒ์ ๋๋ค . ๋ฒ๋ค๋ฌ๊ฐ ์ฌ์ฉํ ๋ชจ๋์ ๊ฒฐ์ ํ ์ ์๋๋ก ๋ค์ํ ๋ฐฉ์์ผ๋ก ๋ณํ๋ ๋ชจ๋์ ๊ฒ์ํ๋ ๊ฒ์ ๋๋ค.
๊ทธ๋ฌ๋ ํ์ฌ ๋ด๋ถ ํจํค์ง์ ๊ฒฝ์ฐ ๋ณํ ์ค์ ์ด ์ฌ๋ฌ ํ๋ก์ ํธ(์: babel ์ฌ์ ์ค์ )์์ ๋์ผํ ์ ์์ผ๋ฉฐ ํด๋ผ์ด์ธํธ ๋ฒ๋ค๋ฌ๊ฐ ๋ชจ๋ ํ์ฌ ์ข ์์ฑ์ ๋ณํํ๋๋ก ํ๋ ๊ฒ์ด ํฉ๋ฆฌ์ ์ ๋๋ค.
@slorber์ ๋งค์ฐ ๋์ํฉ๋๋ค. ํ๋ก์ ํธ๋ฅผ ๋ถํ ํ๊ณ ๊ฐ๋ฅํ ํ ๋ง์ ๊ฒ์ ๊ฒฉ๋ฆฌํ๋ ๊ฒฝ์ฐ ๋ด๋ถ ๋ชจ๋์ ๋งค์ฐ ํธ๋ฆฌํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ RegExp๋ฅผ ์ง์ํ๋ @rauchg / @arunoda ๋ ์ ๋ง ์ข์ ๊ฒ์ด๋ฏ๋ก NPM ์กฐ์ง ๋ค์์คํ์ด์ค๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ๋ ํ์ฌ ๋ด๋ถ ๋ชจ๋์ ํฌ์ฐฉํ๋ ํ๋์ ํญ๋ชฉ์ ๊ฐ์ง ์ ์์ต๋๋ค.
// next.config.js
module.exports = {
transpileModules: [
/^\@my-npm-org\/.*/
]
}
์๋ฆ๋ค์ด ์ ์ @philcockfield
์ด๋ด, ์ด์ฉ๋ฉด ๋ช ๊ฐ์ง ์ฌ์ ์ค์ ์ ์ ๊ณตํ ๊ฐ์น๊ฐ ์์ ์ ์์ต๋๋ค. ๋๋ถ๋ถ์ ๋๊ตฌ(Lerna/npm ๋งํฌ...)๋ ์ฌ๋ณผ๋ฆญ ๋งํฌ์ ์์กดํ๋ฏ๋ก ๋ค์๊ณผ ๊ฐ์ด ๊ฐ๋จํ์ง ์์ ๊ฒ ๊ฐ์ต๋๋ค.
```์๋ฐ์คํฌ๋ฆฝํธ
module.exports = {
transpileModules: ["symlinks"]
}
````
next.js
๋ฅผ ๋ณธ๊ฒฉ์ ์ผ๋ก ์ฌ์ฉํ๊ณ ์ฃผ๋ณ์ ํ๋ถํ ๋ชจ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ตฌ์ถํ ์๋ก ์ด ๊ธฐ๋ฅ์ด ๋ ์ค์ํด์ง๋๋ค. ๋ด ๋ด๋ถ ๋ชจ๋์์ babel ์ปดํ์ผ ๋จ๊ณ๋ฅผ ๋ณต์ ํ๋ ์ค์ PITA๊ฐ ๋๊ณ ์์ต๋๋ค.
๐๐ค
์ค๋๋ ์์ ์ค์ ๋๋ค :)
@philcockfield ํ ๋ฒ ์๋ํด ๋ณด์ธ์: https://github.com/zeit/next.js/pull/749
@arunoda ๊ฐ์ฌ
๋ฐ๋ผ์ PR์ ๋ํด ์ธ๊ธํ๋ฏ์ด ์ด๊ฒ์ด ์ฌ๋ณผ๋ฆญ ๋งํฌ๋ฅผ ์ง์ํ์ง ์์ผ๋ฉด npm ๋งํฌ ๋๋ Lerna์์๋ ์๋ํ์ง ์์ง๋ง ํธ๋์คํ์ผ๋์ง ์์ npm ๋ชจ๋์ ๋ํด์๋ง ๊ธฐ๋ฅ์ด ์ฝ๊ฐ ์ ํ๋ฉ๋๋ค(๋ง์ต๋๊น? ๋ค๋ฅธ ๊ฒ์ ๋ณด์ด์ง ์์ต๋๋ค. /node_modules
๋ด๋ถ์ ๋ชจ๋์ ์ปค๋ฐํ์ง ์๋ ํ ์ ์ค์ผ์ด์ค)
์ฌ๋ณผ๋ฆญ ๋งํฌ๋ฅผ ์ง์ํ์ง ์๋ ์ด์ ๋ ๋ฌด์์ ๋๊น? ์ง์ํ๊ธฐ๊ฐ ๋ ์ด๋ ต์ต๋๊น?
๋ํ ๋ด ์ฑ์์ ๊ทํ์ ๋ถ๊ธฐ๋ฅผ ํ ์คํธํ๊ณ ์ถ์์ง๋ง ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ด ๋ฌด์์ธ์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ๋ธ๋์น๋ฅผ ์ฝ๊ฒ ํ ์คํธํ ์ ์๊ณ ํ ์คํฐ์๊ฒ ๋๋ฌด ๊ณ ํต์ค๋ฝ์ง ์์ ์ ์ฐจ๊ฐ ์์ต๋๊น? ๋๋ ๋ค์๊ณผ ๊ฐ์ ๊ฒ์ ์๋ํ๋ค.
ํ์ฌ ํฌํฌ๋ฅผ ํ ์คํธํ๋ ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ ๋ฌด์์ ๋๊น?
next.config.js
: module.exports = { webpack: (config
์ด ์์
์ ์ํํ๋ ค๋ ๊ฒฝ์ฐ config.module.rules
์ ๋ช ๊ฐ์ง ์ฌํญ์ด ์์ต๋๋ค. ์ด ๊ท์น ์ค ํ๋๋ฅผ ๋ณ๊ฒฝํ๊ฑฐ๋ ์ถ๊ฐํด์ผ ํฉ๋๊น? :
{ loader: 'babel-loader',
include: '/Users/me/gh/guide/node_modules/next/dist/pages',
options:
{ babelrc: false,
cacheDirectory: true,
sourceMaps: 'both',
plugins: [Object] } },
{ test: /\.js(\?[^?]*)?$/,
loader: 'babel-loader',
include:
[ '/Users/me/gh/guide',
'/Users/me/gh/guide/node_modules/next/dist/pages' ],
exclude: [Function: exclude],
query:
{ babelrc: true,
cacheDirectory: true,
sourceMaps: 'both',
presets: [] } } ]
์ ์๋ ๋ ๊ฐ๋จํ ๊ตฌ๋ฌธ์ ๊ธฐ๋ํฉ๋๋ค.
์ ๋ฌด์ง์ ๋ํด ์ฃ์กํฉ๋๋ค. ์ด ๋ฌธ์ ์ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ๋ฌด์์ธ์ง ์ ์ ์์ต๋๊น? ์ฐ๋ฆฌ๋ es6์ ์ฐ๋ฆฌ์ ์ฝ๋๋ฒ ์ด์ค๋ก ๊ฐ์ ธ์ค๊ณ ์ถ์ต๋๋ค. ์ฐ๋ฆฌ๋ tree-shaking์ด ํ์ํฉ๋๋ค.
์ด์ ๋ํ ํ๋ณด๊ฐ ์์ต๋๊น?
@andrewmclagan ์ด ๋ฌธ์ ๋ ์์ง ๊ณต๊ฐ๋์ด ์์ผ๋ฉฐ LernaJS ์ฌ์ฉ์์ ๊ฐ์ด ๋ชจ๋๋ฅผ ๋ง์กฑ์ํค์ง ๋ชปํ ๊ด๋ จ PR ์ด ์์ต๋๋ค.
์ด ์ํ๋ ์ด๋ป์ต๋๊น? node_modules์์ ๊ฐ์ ธ์จ ํ์ผ์ transpileํ๊ธฐ ์ํด next์ webpack์ ๋ง๋๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ด ์์ต๋๊น?
@slorber PR์ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ์ฐ๋ฆฌ์ ์ฌ์ฉ ์ฌ๋ก์ ๊ธฐ์ฌํ์ญ์์ค.
๋น์ทํ ๋ฌธ์ ์ ์ง๋ฉดํด ์์ต๋๋ค. get-urls
ํจํค์ง๋ฅผ ์ฌ์ฉํ๋ ค๊ณ ํฉ๋๋ค. dev
์ฐพ์ ์ ์์ง๋ง ์ปดํ์ผํ ๋ ์๋ํฉ๋๋ค. uglify์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค.
...
{ Error: commons.js from UglifyJs
...
์ด์ ๋ํ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ์์ต๋๊น?
Arunoda๋ ์ธ์ ๊ฐ ์ฌ๊ธฐ์์ ์์ ํ ๊ฒ์ ๋๋ค. ๊ทธ๋ # 749์์ ์ ์ ํ ์ ์ด ์์ต๋๋ค.
์ด ๊ธฐ๋ฅ์ด ๊ตฌํ๋๋ ๊ฒ์ ๋ณด๊ณ ์ถ์ต๋๋ค. @philcockfield๊ฐ ์ธ๊ธํ๋ฏ์ด Next.js ๋ณํ์ ์์กดํ๋ ๋ชจ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ตฌ์ถํ๋ ๊ฒ์ ์ผ๋ฐ์ ์ธ ์๋๋ฆฌ์ค์ด๋ฉฐ ํ๋ก์ ํธ ๊ฐ์ ๊ตฌ์ฑ ์์๋ฅผ ๊ณต์ ํ ์ ์๋ค๋ฉด ์ข์ ๊ฒ์ ๋๋ค.
์ด๊ฒ์ ๋๋ฌด ํ๋ค๊ธฐ์๋ง ํ์ํ ๊ฒ์ ์๋๋๋ค. styled-jsx
์ ๊ฐ์ babel ํ๋ฌ๊ทธ์ธ๋ ๋ง์ฐฌ๊ฐ์ง์
๋๋ค. ๋ฐ๋ผ์ babel ํ๋ฌ๊ทธ์ธ์ ์ฌ์ฉํ๋ ๋ชจ๋(์: ๋ผ์ด๋ธ๋ฌ๋ฆฌ)์ด ์๋ ๊ฒฝ์ฐ ๊ฐ์ฅ ์ข์ ์๋ฃจ์
์ ES6 ์์ค ์ฝ๋๋ฅผ ํฌํจํ๊ณ ์ฑ์ด node_modules์์ ์ด๋ฅผ ํธ๋์คํ์ผํ ์ ์๋๋ก ํ๋ ๊ฒ์
๋๋ค. ๋ฌผ๋ก ๋ค์์๋ ๊ธฐ๋ณธ์ ์ผ๋ก styled-jsx
๊ฐ ์ด๋ฏธ ํฌํจ๋์ด ์์ต๋๋ค.
์ฌ๊ธฐ ๋ด๊ฐ ํ ์ผ์ด ์์ต๋๋ค
// next.config.js
exports.webpack = config => (config.module.rules = config.module.rules.map(({exclude, ...rest}) => ({
exclude: Object.prototype.toString.call(exclude) === '[object Function]' ? (str => !/mycomponents/.test(str) && exclude(str)) : exclude,
...rest
})), config);
๊ธฐ๋ณธ์ ์ผ๋ก ๊ฐ exclude
๋ฅผ ์ฌ์ฉ์ ์ ์ ํจ์๋ก ๋์ฒดํ์ต๋๋ค.
๋๋ ๋ด๊ฐ ๋ฌด์์ ์๋ชปํ๊ณ ์๋์ง ๋ชจ๋ฅด์ง๋ง ๊ทธ๊ฒ์ ์๋์ํฌ ์๋ ์์ต๋๋ค.
node_modules/mycomponents
๋ด์ฉ๋ Next.js๋ก ํธ๋์คํ์ผ๋์ด์ผ ํฉ๋๋ค.
๋ชจ๋ ์ ์ธ๋ฅผ ๋น ๋ฐฐ์ด๋ก ์์ ํ ์ฌ์ ์ํด๋ ์๋ํ์ง ์์ต๋๋ค.
exports.webpack = config => (config.module.rules = config.module.rules.map(({exclude, ...rest}) => ({
exclude: [],
...rest
})), config);
๋์์ฃผ์ธ์ :)
๊ฐ์ฌ ํด์
์๋
ํ์ธ์ ์ฌ๋ฌ๋ถ( @thealjey ) ์ ๋ ์ง๊ธ๊น์ง ๋ช ๋ฌ ๋์ jsnext:main
์ ์ ๋ชจ๋์ ํธ๋์คํ์ผํ๊ณ ์์ต๋๋ค.
jsnext:main
๊ฐ package.json์ ์์ผ๋ฉด ์ง์ ๋ ์ง์
์ ์ ํธ๋์คํ์ผํ๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด main
์๋ ๊ฒ์ ๊ฐ์ ธ์ต๋๋ค.๋๋ next.js
์์ง ์์ง๋ง ๋์์ด ๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
@damianobarbati ์๋์, ๋ถํํ๋ ๊ทธ๋ ์ง ์์ต๋๋ค.
์ด๋ ต์ง ์์ ๊ฒ์ ๋ฌด์์ด๋ ํธ๋์คํ์ผํ๋๋ก webpack์ ์ง์ ๊ตฌ์ฑํ์ง๋ง Next.js์ ์ปจํ
์คํธ์์ ์ด ์์
์ ์ํํ๋ ๋ฐ ์ด๋ ค์์ ๊ฒช๊ณ ์์ต๋๋ค.
์ด๋ด ์ฌ๋ฌ๋ถ, ๋๊ตฌ๋ ์ง ํด๊ฒฐ์ฑ ์ ์ฐพ์์ต๋๊น?
๋ด ํ๋ก์ ํธ์์ ๊ฐ์ ธ์์ผ ํ๋ ๋ก์ปฌ ES6 ์ฐ๊ฒฐ๋ ๋ ธ๋ ๋ชจ๋์ด ์์ง๋ง webpack ๋ถ๋๋ฅผ ์ ๋๋ก ์ป์ ์ ์์ต๋๋ค!
๋ ๋์ ๋ฐฉ๋ฒ์ด ์๋ค๊ณ ํ์ ํ์ง๋ง ๋น๋ ์ babel์ ํตํด ๋ชจ๋ ๊ฒ์ ์คํํฉ๋๋ค.
next build && babel .next/*.js --out-dir . --presets=es2015,react
์ด๊ฑฐ ์ฃฝ์์ด? ์ฌ์ฉ์ ์ ์ ๋ชจ๋์ ๋ณํํ๋ ๋ฐฉ๋ฒ์ ์ฐพ๊ณ ์๋๋ฐ ์ฌ์ ํ ๋ถ๊ฐ๋ฅํ ๊ฒ ๊ฐ์ต๋๋ค.
@mattfelten v5 ๋ก๋๋งต์ ์์ต๋๋ค ๐
๋๊ตฌ๋ ์ง ์ด์ ๋ํ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์๊ฐ ์์ต๋๊น?
@timneutkens ์ด์ ๋ํ ์ผ์ ์ด ์์ต๋๊น? ์ข ์ข ๋ถ๊ฐ๋ฅํ ์ง๋ฌธ์ด์ง๋ง ์ฐ๋ฆฌ๋ ํ์ฌ ์๋ ์ค์ธ ์คํ์ ํ์ธํ๋ ค๊ณ ๋ ธ๋ ฅํ๊ณ ์์ผ๋ฉฐ ์ด๊ฒ์ ์ฐ๋ฆฌ์๊ฒ ๊ฝค ํฐ ๋ฐฉํด ์์์ ๋๋ค! :)
ํด๊ฒฐ ๋ฐฉ๋ฒ ์ ์๋ ์ ํจํฉ๋๋ค.
@thealjey ๋ ์ด๊ฒ์ด ์ค๋๋ ์๊ฒฌ์ด๋ผ๋ ๊ฒ์ ์๊ณ ์์ง๋ง ์ฌ์ ์ํด์ผ ํ include
์ง์ ๋์ด ์๊ธฐ ๋๋ฌธ์ ์๋ฃจ์
์ด ์๋ํ์ง ์์์ ์ ์์ต๋๋ค.
์ ๋ฐ์ดํธ: ์ด ์ ๋ต์ ์ดํด๋ณด์์ง๋ง next.js์ ๋ด๋ถ ๊ตฌ์ฑ ๋ด์ ๋ค๋ฅธ ๋ชจ๋ ๋๋ ํ ๋ฆฌ์ ๋ํ ๋ชจ๋ ๋ค๋ฅธ ๋ก๋๋ฅผ ๊ณ ๋ คํ ๋ ์ ์ ์ ์ด ์๋๋๋ค. ์ด๊ฒ์ ์ผ๊ธ์ด์ด์ผ ํฉ๋๋ค.
@chrisui ๋ด (์์) ์๋ฃจ์
์ ๋ค์๊ณผ ๊ฐ์ด ๊ตฌ์ฑ๋ babel-plugin-module-resolver ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์์ต๋๋ค - "plugins": [["module-resolver", {"root": ["./"]}]]
๊ทธ๊ฒ์ ๊ฒฐ์ฝ ์๋ฒฝํ ์๋ฃจ์
์ ์๋์ง๋ง ๋ค๋ฅธ ๋ชจ๋ ๊ฒ์ด ์คํจํ๊ธฐ ๋๋ฌธ์ ์ง๊ธ์ ์๋ํฉ๋๋ค.
๋๋ถ์ ๊ฐ์ ธ์ฌ ๋๋ง๋ค ๋ง์ ../
๋ฅผ ์ธ ํ์๊ฐ ์์ต๋๋ค.
์ด๊ฒ์ ์ฌ์ฌ์ฉ์ฑ์ ํ์คํ ๋์์ด ๋์ง๋ ์์ง๋ง ์ค์ ๋ก ์ผ๋ถ์๊ฒ๋ ๋ ๋์ ์๋ฃจ์
์ผ ์ ์์ต๋๋ค.
@thealjey ์๋ฅผ ๋ค์ด ์ฃผ์๊ฒ ์ต๋๊น?
๋๋ ์ด๊ฒ์ ์๋ฌด ์์ฉ์ด์๋ ํ๋ก์ ํธ ์ค์ ์ ๊ฐ์ง๊ณ ์์ต๋๋ค ...
https://github.com/jamesgorrie/nappy
๋๋ ํ๋ณต์ด ๋๋ฌด ์ฝ๊ฒ ์ฐ๋ฆฌ์ ์ถ์ ๋ง๋ค ๊ฒ๋ก ํ๋ณด๋ฅผ ์ป์ํ๋ ค๊ณ ์ถ์ง๋ง, ๊ฐ์ ๋ช ๊ฐ์ง ์ง๋ฌธ์ด ์์ต๋๋ค :ํด์ผ๋ next.js
ํน์ ๋ชจ๋์ ์ง์ transpiling ๋๋์ด๋ transpiler๊น์งํด์ผํ์ง๋ง, next.js
๋ ๋ชจ๋ ํด์๋๋ฅผ ๋ณด๋ค ์๊ฒฉํ๊ฒ ๋ฐ๋ฆ
๋๋ค. next.js
๋ฅผ ์ฒ์ ์ ํ๋ ์ฌ๋์ด๋ ์ด๋์๋ถํฐ ์์ํด์ผ ํ ์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
v5์ ๋ก๋๋งต์ ์์ต๋๋ค ๐
@timneutkens ์ด๊ฒ v5๋ก
์๊ณ ์ถ์ด.
๋ณํฉ ๋ ์์น๋ฅผ ์ดํด๋ณด์ญ์์ค. ์ด๊ฒ์ 8 ์ผ ์ ์ ๋ณํฉ๋์์ต๋๋ค. 5.0.0์ด 2์ผ ์ ์ ๋ฆด๋ฆฌ์ค๋์์ต๋๋ค. ์ด๊ฒ์ด ๋ณํฉ๋๋ ์นด๋๋ฆฌ์ ์ง์ ์์ ...
๋๊ตฌ๋ ์ง ์ด๊ฒ์ด ๊ตฌํ๋๋ ๋ฐฉ๋ฒ์ ๋ํ ์๊ฐ ์์ต๋๊น? ์์์ ์ธ๊ธํ ๊ฒ์ฒ๋ผ ์ด๋ ๊ฒ ์๋ํด์ผ ํฉ๋๊น?
module.exports = {
transpileModules: ['my-npm-module']
}
์๋๋ฉด ๋ค๋ฅด๊ฒ ๋ณด์ ๋๊น?
ํผ๋์ค๋ฌ์์. @timneutkens ์์์ ์ธ๊ธํ ๋งํฌ๋ ์์ง ์ด๋ ค ์๋ PR์ ๋ํ ๊ฒ์ ๋๋ค. ์์ง v5์ ๋ณํฉ๋์ง ์์์ต๋๊น?
ํธ์ง: ์ ๊ฒฝ ์ฐ์ง ๋ง์ธ์. ์ด๊ฒ์ ๋จ์ง ์๋ฅผ ๊ฐ์กฐํ๊ธฐ ์ํ PR์ ๋๋ค.
์์์ด๋ ๋ณํฉํ์ง ์๊ณ ๊ทธ๋๋ก ์ฌ์ฉํ์๋ฉด ๋ฉ๋๋ค. transpileModules
๋ ๋์ค์ ๋ค๋ฃฐ ๊ฒ์
๋๋ค.
์ผ๋ฐ์ ์ผ๋ก ๋ฌธ์ ๊ฐ ๊ณต๊ฐ๋๋ฉด ๊ณต๊ฐ๋์ง ์์ต๋๋ค.
@brianyingling ์์ ์๋ฃจ์
(v5 ์ ์ฉ)์ ์ํ ํ๋ฌ๊ทธ์ธ์ผ๋ก ์์ ๋ฅผ ๋ณํํ์ต๋๋ค.
๋ณด๋ค ๊ฐ๋ ฅํ๊ณ ๊ณต์์ ์ธ ์๋ฃจ์
์ด ๋ง๋ จ๋ ๋๊น์ง ํ์ฌ๋ก์๋ ์๋ํ๊ณ ์์ต๋๋ค.
https://www.npmjs.com/package/@weco/next -plugin-transpile-modules
์ ํ๋ฆฌ์ผ์ด์ ์ฝ๋๋ฒ ์ด์ค์ ๋จ์ผ ๋ชจ๋์ ๋ํ ์ด์ ๋ํ ์๋ฅผ ๋ณด๊ณ ์ถ์ต๋๋ค.
์๋ฅผ ๋ค์ด, ์๋ฒ ์ธก๊ณผ ํด๋ผ์ด์ธํธ ์ธก ๋ชจ๋๋ฅผ ์ฌ์ฉํ๋ ๋ชจ๋์ด ์์ต๋๋ค. ๋ชจ๋์ ์์ฒด ๋ณ๋์ ๋ชจ๋๋ก ๋ถํดํ๊ณ yarn link
ํ๊ฑฐ๋ webpack ๊ท์น์ ํดํนํ์ฌ ์์ ์์ ๋ฅผ ์๋์ํค์ง ๋ชปํ์ต๋๋ค.
๋ค์์ ๊ฐ๋จํ ์ฌํ์ ๋๋ค. https://github.com/statico/nextjs-with-async-lib
// pages/index.js
import { foo } from '../lib/test'
export default () => <div>hello {String(typeof foo)}</div>
// lib/test.js
async function foo () {}
module.exports = { foo }
@timneutkens ๋ ์ด๊ฒ์ด ๊ณต์ ๋ชจ๋์์ async/await
๋ฅผ ์ฌ์ฉํ๊ณ ์๊ธฐ ๋๋ฌธ ์ด๋ผ๊ณ ๋งํฉ๋๋ค. ๋ด ์๋ฃจ์
์ async/await๋ฅผ ์ ๊ฑฐํ๊ณ ๋ชจ๋ ๊ฒ์ .then()
์คํ์ผ ์ฝ๋ฐฑ์ผ๋ก ๋ณ๊ฒฝํ๋ ๊ฒ์ผ ์ ์์ต๋๋ค.
์๊ฒ ์ต๋๋ค. ์ ์๊ฒ ๋ง๋ ์์ ์ฌํญ์ ์ฐพ์์ต๋๋ค.
๋จผ์ https://github.com/zeit/next.js/issues/3018#issuecomment -380879576์ ๋ฐ๋ผ config.resolve.symlinks = false
์ค์ ์ next.config.js
๊ตฌ์ฑ์ ์ถ๊ฐํ์ต๋๋ค.
// next.config.js
webpack: (config, { dev }) => {
config.resolve.symlinks = false
return config
}
๊ทธ๋ฐ ๋ค์ CommonJS ๋ด๋ณด๋ด๊ธฐ ๋ฐ async
/ await
ํค์๋๋ฅผ ์ฌ์ฉํ๋ .js
ํ์ผ์ shared
๋ผ๋ ์์ฉ ํ๋ก๊ทธ๋จ์ ํ์ ๋๋ ํฐ๋ฆฌ์ ๋ฃ์ต๋๋ค.
// shared/index.js
async function foo () {}
module.exports = { foo }
// shared/package.json
{
"name": "@myapp/shared",
"version": "1.0.0",
"main": "index.js",
"license": "UNLICENSED",
"private": true,
"dependencies": { ... }
}
๊ทธ๋ฆฌ๊ณ ๋ง์ง๋ง์ผ๋ก ๋ฉ์ธ ์ ํ๋ฆฌ์ผ์ด์
์์ ๋๊ตฐ๊ฐ๊ฐ yarn install
๋ฅผ ํ ๋ ์ด๋ฅผ ๋ชจ๋ ์ฐ๊ฒฐํ๊ธฐ ์ํด postinstall
์คํฌ๋ฆฝํธ๋ฅผ ์ถ๊ฐํ์ต๋๋ค.
// package.json
{
...
"scripts": {
"postinstall": "cd shared ; yarn -s unlink ; yarn link && yarn && cd .. && yarn link @myapp/shared",
...
์ด์ ๋ด Mocha ํ
์คํธ๊ฐ ์๋ฒ ์ธก์์ ํต๊ณผํ๊ณ ๋ด ์ฌ์ฉ์ ์ง์ Koa ์๋ฒ๊ฐ ์ ๋๋ก ์์๋๊ณ ๋ด NextJS ํ์ด์ง์ ๋ ์ด์ ๋ฏธ์น Cannot assign to read only property 'exports' of object '#<Object>'
๊ฐ ์์ต๋๋ค.
NextJs 5.1.0์ผ๋ก ์
๊ทธ๋ ์ด๋ํ ๋๋ ์ด์ ๋์ผํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค. ๋ค์ ๋
ธ๋ ๋ชจ๋ ์ค ํ๋ ๋๋ ๋ ๊ฐ๋ ๋ฑ๋ฑํ ํ์ดํ ๊ธฐ๋ฅ์ ๋ณํํ์ง ์๊ณ IE11์์ ์ค๋ฅ๋ฅผ ๋์ก์ต๋๋ค. ๋๋ ์ด์ ์ ๊ฐ๋ณ polyfills์ ์ค์ ํ๋ ๊ณผ์ ์๊ณ , ๊ฒฐ๊ตญ ๋ด๊ฐ ๊ฐ์ง ๊ทธ ๋ชจ๋ ํ์ผ์ ๋์์ผ๋ก ์ ํํ๋ค babel-polyfill
๋ด์์ next.config.js
์ด๊ณผ๋ฅผ :
module.exports = {
webpack: (config, { dev }) => {
const polyfill = new Promise((resolve, reject) => {
const originalEntry = config.entry
originalEntry().then(entries => {
if (entries['main.js']) {
entries['main.js'].unshift('./client/polyfills.js')
entries['main.js'].unshift('babel-polyfill')
}
config.entry = entries
resolve()
})
})
config.module.rules.push(
{
test: path.resolve('./node_modules/next/node_modules/'),
loader: 'babel-loader',
options: {
babelrc: false,
cacheDirectory: false,
presets: ['es2015']
}
}
)
return polyfill.then(() => { return config })
}
}
์ด๊ฒ์ด ๋๊ตฐ๊ฐ๋ฅผ ๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
ESM ์ ๋งค๋ ฅ์ฒ๋ผ ์๋ํฉ๋๋ค.
index.js
์ ์ฌ์ฉ์ ์ ์ Next.js ์๋ฒ๋ฅผ ์ฌ์ฉํ์ฌ ์ด ๋ช
๋ น์ ์คํํ์ฌ ์๋ฒ๋ฅผ ์์ํ ์ ์๊ณ esm์ด ์๋ฒฝํ๊ฒ ์์๋์ด Lerna-symlinked ํ๋ก์ ํธ ํจํค์ง์์ ES ๋ชจ๋์ ํด๊ฒฐํฉ๋๋ค.
node -r esm index.js
@curran ๋ฉ์ง, babel-node๋ฅผ ๋์ฒดํ ์ ์์ต๋๊น?
@curran ๋๋ ํ๋ก๋์ ์์ ๊ทธ๋ ๊ฒํ์ง ์์ ๊ฒ์ ๋๋ค.
@blackbing ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
@thealjey ์ ๊ทธ๋?
๋๊ตฌ๋ ์ง ๋น ๋ฅด๊ณ ์ฌ์ด ์๋ฃจ์
์ ์ฐพ๊ณ ์๋ค๋ฉด ์ฌ๊ธฐ ๋ด๊ฐ ํ ์ผ์ด ์์ต๋๋ค. ๋
๋ฆฝ ์คํํ Node ์คํฌ๋ฆฝํธ๋ฅผ ํตํด ๋ฐฑ์๋์ NextJS๋ฅผ ํตํด ํด๋ผ์ด์ธํธ ๋ชจ๋์์ ์คํํ๋ ค๋ ์ฝ๋๊ฐ ํฌํจ๋ shared/
ํ์ ๋๋ ํ ๋ฆฌ๋ฅผ ๋ง๋ค์์ต๋๋ค. ์์ฒด package.json
๊ฐ ์๊ณ ์ด๋ฆ์ @myproject/shared
๋ก ์ ์ธํฉ๋๋ค.
๊ทธ๋ฐ ๋ค์ ๊ธฐ๋ณธ(์์) ํ๋ก์ ํธ์์ ๋ค์๊ณผ ๊ฐ์ด ์ฌํ ์ค์น ์คํฌ๋ฆฝํธ๋ฅผ package.json
ํ์ต๋๋ค. cd shared && yarn -s unlink >/dev/null 2>&1 ; yarn -s link && yarn -s && yarn link @myproject/shared
โ ๊ทธ๋ฐ ๋ค์ yarn
๋ฅผ ํ ๋ฒ ์ด์ ์คํํ๊ณ ๊ฐ์ ธ์ค๊ธฐ๋ฅผ import { whatever } from '@myproject/shared/somefile'
๋ณ๊ฒฝํฉ๋๋ค.
์ด๋ ๊ฒ ํ๋ฉด ๊ณต์ ์ฝ๋๊ฐ ๋ฏธ์น ๋ณํ ๋จ๊ณ ์์ด ์๋ํ๋ฉฐ yarn link
๊ฐ ์
๋ฐ์ดํธ๋ฅผ ๋ง๋ค ๋๋ง๋ค yarn
/ npm
๋ฅผ ๋ค์ ์คํํ ํ์๊ฐ ์์ต๋๋ค. ์ฌ๋ณผ๋ฆญ ๋งํฌ.
TypeScript๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ @weco/next-plugin-transpile-modules
๊ฐ ์๋ํ์ง ์์ต๋๋ค. Next์ withTypescript
๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด ํฌํฌ๋ฅผ ๋ง๋ค์์ต๋๋ค. https://github.com/KeitIG/next-plugin-transpile-modules
๊ทธ๋๋ TypeScript์ ์๋ฒ ์ธก ์ฝ๋๊ฐ ํ์ํ ๋ ์ ๋๋ก ์ํํ๋ ๋ฐฉ๋ฒ์ ์์๋ด์ผ ํฉ๋๋ค.
์ด๊ฒ์ ๋ํ ์์์ด ์์ต๋๊น?
@bogdansoare https://github.com/KeitIG/next-plugin-transpile-modules๋ฅผ ์ฌ์ฉํ๊ณ
๊ทธ๋ฆฌ๊ณ ๋ค์ ์์ง์์ ๋ด๊ฐ ํ ๋ ๋ค๋ฅธ ๊ฒ. TypeScript ๋ฐ ๋ชจ๋ ํจํค์ง๊ฐ ์๋ @scope
์ ํน์ ํจํค์ง๋ ์ฒ๋ฆฌํฉ๋๋ค. https://gist.github.com/trusktr/44400d0d016c506629b4f914799dc9cd
esm
๋ฐ lerna
๋ฅผ ์ฌ์ฉํ๋ ๊ฐ๋จํ ์์
์์ ๋ฅผ ๋ง๋ค์์ต๋๋ค.
https://github.com/curran/nextjs-esm-example
/cc @jdalton
๊ฐ์ธ์ ์ผ๋ก ๋ค์ next.config.js
.
module.exports = {
webpack: (config, options) => {
config.module.rules.push({
test: /\.js$/,
include: /node_modules/,
use: [
options.defaultLoaders.babel
]
})
return config
}
}
IE 11 ํธํ์ฑ์ ๋ฌ์ฑํ๊ธฐ ์ํด ํ์ํ node_modules
๋ชจ๋ ๊ฒ์ babels ...
๋ํ ๋ด ํ๋ก์ ํธ์ ๋ณํ๋์ง ์์ npm ํจํค์ง๋ฅผ ์ถ๊ฐํ๋ ๋ฐ ์ด๋ ค์์ ๊ฒช๊ณ ์๋ ์ด์ ๋ํ ์๋ฃจ์
์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค. ์ง๊ธ์ ๊ณต๊ธ์
์ฒด์ ๋ค์ด๋ก๋ํด์ผ ํ์ต๋๋ค/:(
์ ๋ง ์ง์ฆ๋๋ค
@bel0v ๋๋ ๋น์ ์ด ์ด๋ฏธ next-plugin-transpile-modules
์ด๊ฒ์ ๋ฌ์ฑํ ์ ์์ด์ผ ํ๋ค๊ณ ๋ฏฟ์ต๋๋ค. ์ด ๋ฌธ์ ๋ ๋ซํ ์์ด์ผ ํฉ๋๋ค. cc/ @timneutkens
์ฌ์ ํ ๋์ฒด ์๋ฃจ์ ์ ์กฐ์ฌํ๊ณ ์ถ์ต๋๋ค.
์ต๊ทผ Jamie๋ node_modules ์ปดํ์ผ ๋ฌธ์ ์ ๋ํด ๋งค์ฐ ์์ธํ ์ค๋ ๋๋ฅผ ์์ฑํ์ต๋๋ค. https://twitter.com/jamiebuilds/status/1080840492525350912
Jamie์ ์ค๋ ๋๋ฅผ ์ฝ์์ง๋ง ์ด ์ํฉ๊ณผ ์๋ฃจ์
์ ๋ํ Henry Zhu์ Babel์ ๊ฒฌํด๋ ๊ณต์ ํ๊ณ ์ถ์ต๋๋ค.
https://babeljs.io/blog/2018/06/26/on-consuming-and-publishing-es2015+-packages
(Tim์ ๋์ํ์ง ์๋ ๊ฒ์ด ์๋๋ผ ๋ง์ ์ฅ๋จ์ ์ ๊ณต์ ํ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ต๋๋ค. Tim์ด ๋์ ์๋ฃจ์ ์ ์กฐ์ฌํ๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค.)
๋ค ์ ํฌ๋ ์ง๋ ๋ฐ๋ ๋์ ์ด ๋ฌธ์ ์ ๋ํด Henry๋ฅผ ํฌํจํ์ฌ ๋ง์ ์ฌ๋๋ค๊ณผ ์ด์ผ๊ธฐ๋ฅผ ๋๋์์ต๋๋ค ๐
node_modules ํธ๋์คํ์ผ์ ๋ํ ์ฐ๋ ค์๋ ๋ถ๊ตฌํ๊ณ ์์ ์ ํจํค์ง๋ฅผ monorepo์ ํธ๋์คํ์ผํ๋ ค๋ ๊ฒ์ ์ด๋ฌํ ์ฐ๋ ค๊ฐ ์ ์ฉ๋์ง ์๋ ๋งค์ฐ ์ผ๋ฐ์ ์ธ ์๊ตฌ ์ฌํญ์ ๋๋ค.
@dcalhoun ์๋ํ์ง๋ง ๋ถํํ๋ ์ฌ์ ํ ์๊ธฐ์น ์์ ํ ํฐ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค. ์ด ํ๋ฌ๊ทธ์ธ์๋ ๊ด๋ จ์ด ์์ ์ ์๋ ์ด๋ฆฐ Next 7 ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
@bel0v
FAQ๋ฅผ ์ฝ์ด์ผ ํฉ๋๋ค ;) ์ด ๋ฌธ์ ์ ๋ํ ํด๊ฒฐ์ฑ ์ด ์์ต๋๋ค: https://github.com/martpie/next-plugin-transpile-modules#i -have-trouble-making-it-work-with-nextjs-7
์ฌ๋ฌ ํ๋ก์ ํธ์์ ์ด ํ๋ฌ๊ทธ์ธ์ ์ฌ์ฉํด ์์ผ๋ฉฐ ์์ ์ด ์ ์ํ๋ฉ๋๋ค. Next 7 ๋ฌธ์ ๋ ์ด์ํฉ๋๋ค. ์ด๊ฒ์ด Next ๋๋ Babel์์ ์ค๋ ๊ฒ์ธ์ง ํ์คํ์ง ์์ต๋๋ค. ์ด์จ๋ ์ฌ๊ธฐ์์ ๋ฌธ์ ๋ฅผ ์ด์์ต๋๋ค: https://github.com/zeit/next.js/issues/5393
@martpie ๋ค ํด๋ณธ๊ฑฐ ๊ฐ์์..์ด์จ๋
@martpie ์ฐ๋ฆฌ๋ ์ผ๊ด๋ babel.config.js ๋ฐ yarn ์์ ๊ณต๊ฐ์ผ๋ก next7์ ์ฌ์ฉํ๊ธฐ ์์ํ์ต๋๋ค. ๊ฐ๋จํ ์์ ๋ฅผ ์ค์ ํ ์ ์๋์ง ์ ์ ์์ต๋๋ค.
์ฌ๊ธฐ์์ ๊ธฐ๋ณธ ์์ ๋ฅผ ๋ถ๊ธฐํ์ต๋๋ค.
https://github.com/bel0v/learnnextjs-demo
๊ฑฐ๊ธฐ์ ๋ณํ๋์ง ์์ ์ข
์์ฑ(wired-elements)์ ์ค์นํ๊ณ ๋น๋ ์ค๋ฅ Unhandled Rejection (SyntaxError): Unexpected token {
์ป์๊ณ ์ ์๋ ๋ฐฉ์์ผ๋ก ์์ ํ๋ ค๊ณ ํ์ต๋๋ค.
์๋ํ๋ ค๋ฉด ์ถ๊ฐ babel ํ๋ฌ๊ทธ์ธ์ด ํ์ํ ๊ฒ ๊ฐ์ต๋๋ค. ๐ค
@bel0v FAQ์ ๋ค์ Lerna ์ค์ ์ด ์๋ํ์ง ์๋ ์ด์ ์ ๋ํ ์ค๋ช ์ด ์์ต๋๋ค.
@martpie ์, ์์์ด์! ํ์ฌ ํจํค์ง๊ฐ Lerna๋ก ์ค์ ๋์๋ค๋ ์ฌ์ค์ ๋ชฐ๋์ต๋๋ค. ๊ฐ์ฌ ํด์
https://twitter.com/jamiebuilds ๊ฐ ์ผ์ ์ค๋จ๋ ๊ฒ ๊ฐ์์ ๋ ์ด์ ์ค๋ ๋๋ฅผ ์ฝ์ ์ ์์ต๋๋ค. #3018 ์ด ๋ฌธ์ ์ ๊ด๋ จํ์ฌ ํ์๋์์ผ๋ฏ๋ก ๊ณ ๋ ค ์ค์ธ ๋์ฒด ์ ๊ทผ ๋ฐฉ์์ด ๋ฌด์์ธ์ง ๊ถ๊ธํฉ๋๋ค.
์ด๊ฒ๋ค์ ์ด๋ฌํ ์ฌ์ฉ ์ฌ๋ก atm์ ๋ํ next.js์ ์ต์ ๊ธฐ์ /๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ํ๋
๋๊น?
https://github.com/curran/nextjs-esm-example
https://github.com/wellcometrust/next-plugin-transpile-modules
https://github.com/martpie/next-transpile-modules
https://github.com/zeit/next.js/tree/canary/examples/with-yarn-workspaces
๋ฐ๋ผ์ ์ ์ฒ๋ผ IE11์ ์ง์ํด์ผ ํ๋ ํ๋ก์ ํธ์์ ์์
ํ๋ ๊ฒฝ์ฐ node_modules/
๋ด๋ถ์ ๋ชจ๋ ์ฝ๋๋ฅผ ์ค์ ๋ก ๋ณํํด์ผ ํฉ๋๋ค. Next.js 7.x์์๋ ๋ค์ ์ค์ ์ ์ฌ์ฉํ๋๋ฐ ์ ์๋ํ์ต๋๋ค.
๋ถํํ๋, ๊ธฐ๋ณธ ๋ด๋ณด๋ด๊ธฐ๊ฐ ์๊ธฐ ๋๋ฌธ์ ๋ชจ๋์ด ๋ค๋ฅธ ๋ชจ๋์ ๊ฐ์ ธ์ค์ง ๋ชปํ๋ค๋ ์ค๋ฅ์ ํจ๊ป Next.js 8.x์์ ์๋์ด ์ค์ง๋์์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ node_modules/
์ ์ฝ๋๋ง @babel/preset-env
๋ก ๋ณํํ๊ณ ๋ค๋ฅธ ํ๋ฌ๊ทธ์ธ์ ์๋ Next.js 8.x์ ๋ํ ์๋ ๊ตฌ์ฑ์ ์๊ฐํด ๋์ต๋๋ค.
์ด๊ฒ์ package.json
๋ด browserlist
์์ฑ์ ์ค์ ํ์ฌ ๊ฒฐํฉ๋ฉ๋๋ค.
"browserslist": "defaults, IE >= 11, EDGE >= 14, Safari >= 11, Chrome >= 41, Firefox >= 52",
next.config.js
module.exports = {
webpack: (config, options) => {
config.module.rules.push({
test: /\.js$/,
include: /node_modules/,
use: [
options.defaultLoaders.babel,
],
})
return config
},
}
next.config.js
module.exports = {
webpack: (config, options) => {
config.module.rules.push({
test: /\.js$/,
include: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: ['@babel/plugin-syntax-dynamic-import'],
},
},
})
return config
},
}
๋ถํํ๋ ์์ง ์ด ์ค์ ์์ @babel/plugin-transform-runtime
๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ ์ฝ๋์์ ๊ฝค ๋ง์ ๋์ฐ๋ฏธ๊ฐ ๋์ฌ ๊ฒ์
๋๋ค ๐ gzip์ด ์ฒ๋ฆฌํด ์ฃผ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค ๐ ๐
Next.js๊ฐ node_modules/
๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ๋ณํํ์ฌ browserlist
์ ํจ๊ป ์ฌ์ฉํ ์ ์๋ ์ต์
์ ์ ๊ณตํ ์ ์๋ค๋ฉด ์ ๋ง ์ข์ ๊ฒ์
๋๋ค. ๊ธฐ์
์ฌ์ฉ์๊ฐ ์๋ ๋๊ท๋ชจ ์ฌ์ดํธ๋ ์ด์ ๋ธ๋ผ์ฐ์ ๋ฅผ ์ ๋๋ก ์ง์ํ๊ธฐ ์ํด ์ด์ ์์กดํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
next-transpile-modules
(@jamesgorrie์ ๋ฉ์ง ์์
์ ๊ธฐ๋ฐ์ผ๋ก ํจ)์ ๊ด๋ฆฌ์๋ก์ ์ฌ๊ธฐ์์ ์ด ๋ฌธ์ ์ ์ง๋ฉดํ ์ฌ๋์ ๋์ธ ์ ์์ด ๊ธฐ์ฉ๋๋ค.
์ ๋ ์ด ํ๋ฌ๊ทธ์ธ์ ์ฌ์ฉํ์ฌ 1๋ ์ด์ ์ ๋ฌธ ํ๋ก์ ํธ๋ฅผ ์งํํด ์์ผ๋ฉฐ ์ง๊ธ๊น์ง ํ๋ฅญํ๊ฒ ์๋ํ์ต๋๋ค.
Next.js์ ๊ธฐ๋ณธ ์ง์์ ๋ฌผ๋ก ํ๋ฅญํ ๊ฒ์ด๋ฉฐ ์ด ๊ธฐ๋ฅ์ next
ํจํค์ง์ ํตํฉํ๋ ๋ฐ ๋์์ ๋๋ฆฌ๊ฒ ์ต๋๋ค. ๋๋ Tim์ด ์๋ํ๊ณ ์ถ์ ๋ช ๊ฐ์ง ์์ด๋์ด๊ฐ ์๋ค๋ ๊ฒ์ ์๊ณ ์์ง๋ง ์ด์จ๋ .
๊ฑด๋ฐฐ!
@martpie ๋น ๋ฅด๊ฒ ํ๋ก์ ํธ๋ฅผ ์ดํด๋ณด์์ง๋ง _all_ ๋ชจ๋์ ๋น ๋ฅด๊ฒ ๋ณํํ๋ ๋ฐฉ๋ฒ์ ์ฐพ์ง ๋ชปํ์ต๋๋ค. ๊ฐ๋ฅํ๊ฐ์? โบ๏ธ
๋ํ options.defaultLoaders.babel
ํ๊ณ ์ด๋ฅผ babel loader๋ก ์ฌ์ฉํ๊ณ ์์ต๋๋ค. Next.js 8.x๋ก ๊ทธ๋ ๊ฒ ํ ๋ ์ผ๋ถ ๋ชจ๋์ด ๊ทธ ํ์ CJS ๋ชจ๋๋ก ์ ๋๋ก ์ธ์๋์ง ์๊ณ ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ๊ฐ์ ธ์ค์ง ๋ชปํ๋ ๋ฌธ์ ๊ฐ ์์์ต๋๋ค. ์:
./pages/_glamor.js
Attempted import error: 'css' is not exported from 'glamor'.
./components/project-selector.js
Attempted import error: 'react-select/lib/Async' does not contain a default export (imported as 'AsyncSelect').
./node_modules/react-select/dist/react-select.esm.js
Attempted import error: 'react-input-autosize' does not contain a default export (imported as 'AutosizeInput').
./pages/signup/full.js
Attempted import error: 'react-select/lib/Creatable' does not contain a default export (imported as 'CreatableSelect').
./components/markdown-editor.js
Attempted import error: 'react-simplemde-editor' does not contain a default export (imported as 'SimpleMDEEditor').
./components/pagination.js
Attempted import error: 'react-js-pagination' does not contain a default export (imported as 'UpstreamPagination').
./node_modules/react-google-recaptcha/lib/es/recaptcha-wrapper.js
Attempted import error: 'react-async-script' does not contain a default export (imported as 'makeAsyncScriptLoader').
./pages/_glamor.js
Attempted import error: 'rehydrate' is not exported from 'glamor'.
๊ทธ๋์ preset-env
์ฌ์ฉํ์ฌ ์ฝ๋๋ฅผ ๋ณํํ๊ณ Next.js ๊ด๋ จ ๋ณํ์ ๊ฑด๋๋ฐ๋ node_modules/
๋ํ ์ฌ์ฉ์ ์ง์ babel ๊ตฌ์ฑ์ ์ ๊ณตํ๋๋ก ์ ํํ์ต๋๋ค. ์ด ์ ๊ทผ ๋ฐฉ์์ ๋ํด ์ด๋ป๊ฒ ์๊ฐํ์ญ๋๊น?
๊ฑด๋ฐฐ ๐ป
@LinusU transpileModules: ['(.*?)']
์๋ํด๋ณด๊ณ ์๋ํ๋์ง ์๋ ค์ฃผ์๊ฒ ์ต๋๊น?
๊ทธ๋ฌ๋ ํฅํ ์ฃผ์ ๋ฆด๋ฆฌ์ค์์๋ ์๋ํ์ง ์์ ์ ์์ผ๋ฏ๋ก ์ฃผ์ํ์ญ์์ค.
๋ ์ผ๋ฐ์ ์ผ๋ก, ์ ์ฒด node_modules
ํด๋๋ฅผ ํธ๋์คํ์ผํ๋ ๊ฒ์ ๊ถ์ฅํ์ง ์์ต๋๋ค("๋งค์ฐ ๊ถ์ฅํ์ง ์์" ์ฐธ์กฐ). ์ปดํ์ผํ๋ ๋ฐ ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๊ณ ํจํค์ง๋ ES3 ํธํ ์ฝ๋(IE11 ํธํ ๊ฐ๋ฅ)๋ฅผ ์ ๊ณตํด์ผ ํฉ๋๋ค.
ํ์ํ ๋ชจ๋๋ง ํธ๋์คํ์ผํ์ธ์! ( lodash-es
, ๋ก์ปฌ ๋ชจ๋ ๋ฑ...)
ํจํค์ง๋ ES3 ํธํ ์ฝ๋๋ฅผ ์ ๊ณตํด์ผ ํฉ๋๋ค(IE11 ํธํ ๊ฐ๋ฅ).
์ด๊ฒ์ ๋ด๊ฐ ๋ณธ ํ์ค์ด ์๋๋ฉฐ ์ค์ ๋ก ๋์ํ์ง ์์ต๋๋ค. ๋ชจ๋ ์์ฑ์๋ ๋ด๊ฐ ๋์์ผ๋ก ํ๋ ๋ธ๋ผ์ฐ์ ๋ฅผ ์ ํํ ์์ง ๋ชปํ๋ฉฐ ์ด์ ์ฝ๋๋ฅผ ์ ๊ณตํ๋ ๊ฒฝ์ฐ ์ต์ ๋ธ๋ผ์ฐ์ ๋ฅผ ๋์์ผ๋ก ํ๋ ์ฌ์ฉ์์๊ฒ ์ ์ฌ์ ์ผ๋ก ๋ถ์ด์ต์ ์ค ๊ฒ์ ๋๋ค.
์ปดํ์ผํ๋ ๋ฐ ์์ํ ๊ฑธ๋ฆด ๊ฒ์ ๋๋ค
์์ํ ๋ ์ฝ๊ฐ ๋๋ฆฌ์ง๋ง ๊ทธ ํ์๋ ์บ์๋ ๊ฒ ๊ฐ๊ณ ํน์ ํ์ด์ง๋ฅผ ๋ณ๊ฒฝํ ๋ ๊ฑฐ์ ์ฆ์ ๋ค์ ๋ก๋๋๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
ํ์ํ ๋ชจ๋๋ง ํธ๋์คํ์ผํ์ธ์!
์ด๋ฅผ ์ํด์๋ IE11๊ณผ ํธํ๋๋ ํจํค์ง์ ํธํ๋์ง ์๋ ํจํค์ง๋ฅผ ์ ํํ ์์์ผ ํ๋ฉฐ ์ข ์์ฑ(์ผ์์ ์ธ ์ข ์์ฑ ํฌํจ)์ด ๋ณ๊ฒฝ๋ ๋๋ง๋ค ์ด ์ ๋ณด๋ฅผ ์ต์ ์ํ๋ก ์ ์งํด์ผ ํฉ๋๋ค. ๐ค ํ์ค์ ์ด์ง ๋ชปํ๋ค.
์ค์ํ ๊ฒ์ package.json module
์ ๊ณต๋๋ ESM ์ง์
์ ์ ์ผ๋ฐ์ ์ผ๋ก ํธ๋ฆฌ ์์ดํน์ ์ํ ES6 ๊ฐ์ ธ์ค๊ธฐ/๋ด๋ณด๋ด๊ธฐ๊ฐ ํฌํจ๋ ES5๋ผ๋ ๊ฒ ์
๋๋ค. ๋ฐ๋ผ์ ์ด๊ฒ์ ๋ฌ๋ฆฌ ๋ช
์๋์ง ์๋ ํ ํธ๋์คํ์ผ๋ฌ(Babel)๊ฐ ์๋ ๋ฒ๋ค๋ฌ(Webpack)์ ๋ํ ์์
์
๋๋ค. ์ ๊ด๋ฆฌ๋๋ ๋ง์ ํจํค์ง์๋ ์ด๋ฏธ ESM ์ง์
์ ์ด ์์ต๋๋ค. ์๋ฅผ ๋ค์ด OP๊ฐ ์ธ๊ธํ Redux์ ๊ฒฝ์ฐ redux/es
์
๋๋ค.
next.config.js
:module.exports = { webpack: (config
์ด ์์ ์ ์ํํ๋ ค๋ ๊ฒฝ์ฐconfig.module.rules
์ ๋ช ๊ฐ์ง ์ฌํญ์ด ์์ต๋๋ค. ์ด ๊ท์น ์ค ํ๋๋ฅผ ๋ณ๊ฒฝํ๊ฑฐ๋ ์ถ๊ฐํด์ผ ํฉ๋๊น? :{ loader: 'babel-loader', include: '/Users/me/gh/guide/node_modules/next/dist/pages', options: { babelrc: false, cacheDirectory: true, sourceMaps: 'both', plugins: [Object] } }, { test: /\.js(\?[^?]*)?$/, loader: 'babel-loader', include: [ '/Users/me/gh/guide', '/Users/me/gh/guide/node_modules/next/dist/pages' ], exclude: [Function: exclude], query: { babelrc: true, cacheDirectory: true, sourceMaps: 'both', presets: [] } } ]
์ ์๋ ๋ ๊ฐ๋จํ ๊ตฌ๋ฌธ์ ๊ธฐ๋ํฉ๋๋ค.
๋๋ฅผ ์ํด ์ ์๋
{
test: /\.js(\?[^?]*)?$/,
loader: 'babel-loader',
include: [
path.resolve(__dirname, './node_modules/next/dist/pages'),
],
query: {
cacheDirectory: true,
sourceMaps: 'both',
presets: ['@babel/preset-env'],
plugins: ['@babel/plugin-proposal-object-rest-spread']
}
},
๋๋ Lerna ๋ชจ๋ ธ ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ด ๋ฌธ์ ์ ๋ถ๋ช์ณค๊ณ ์์ธ์ด ๋ฌด์์ธ์ง์ ๋ํด ๋จธ๋ฆฌ๋ฅผ ๊ธ์ ์์ต๋๋ค. ์ค๋ฅ๋ webpack์์ ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ ๋ก๋๊ฐ ๋๋ฝ๋ ๊ฒ ์ธ์๋ ๋์์ด ๋์ง ์๋ ์ข์ ์ธ๋ถ ์ ๋ณด๋ฅผ ์ ๊ณตํ์ง ์์ต๋๋ค. ๊ณ ๋ง๊ฒ๋ ์ด github ๋ฌธ์ ๋ฅผ ์ฐพ์์ต๋๋ค!
์ด ๋ฌธ์ ๋ฅผ ๊ฒ์ํ๊ณ Lerna๋ ์ฌ์ฉํ๊ณ ์๋ ๋ค๋ฅธ ์ฌ๋์ ์ํด ์ฌ๊ธฐ์ ๋ด ์๋ฃจ์ ์ ๋จ๊ธธ ๊ฒ์ ๋๋ค.
์์ค๋ฅผ dist ๋๋ ํ ๋ฆฌ๋ก ๋ณํํ๊ณ ๋งํฌํ ๋ dist ๋๋ ํ ๋ฆฌ๋ฅผ ๊ฐ๋ฆฌํค๋๋ก Lerna์ ์ง์ํ๋ ๊ณต์ ํจํค์ง์ ๋ํ ์ฌ์ ๊ณต๊ฐ ์คํฌ๋ฆฝํธ๋ฅผ ์์ฑํ์ญ์์ค.
// package.json
"main": "dist",
"scripts": {
// I'm using the react-app preset because it's easy
"prepublish": "babel --presets react-app --plugins @babel/plugin-transform-modules-commonjs src --out-dir dist"
},
// This instructs Lerna to use dist when symlinking
"publishConfig": {
"directory": "dist"
}
์ด์ lerna bootstrap
ํ ๋ ์ฌ์ ๊ฒ์ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ๊ณ ์์ค๋ฅผ ๋ณํํ์ฌ Next์์ ์ฌ์ฉํ ์ ์๋๋ก ํฉ๋๋ค.
lerna
๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ next-transpile-modules๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ๋ณผ๋ฆญ ๋งํฌ๋ฅผ ๋ง๋ค์ด ํธ๋์คํ์ผํ ์ ์์ต๋๋ค. lerna
์ ํจ๊ป ํด๋น ํจํค์ง๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ฌธ์ ๋งจ ์๋์ ๋์ ์์ต๋๋ค.
NextJs ์ฑ์์ ์ฝ๋ ๊ณต์ ๋ฅผ ๊ฒ์ํ๋ ์ฌ๋์ ์ํด ๋ชจ๋ ธ ์ ์ฅ์์์ ์ฌ๋ฌ NextJs ์ฑ ๊ฐ์ React ๊ตฌ์ฑ ์์์ ์ ํธ๋ฆฌํฐ๋ฅผ ๊ณต์ ํ๋ ค๊ณ ํ ๋ @LinusU ์ ์๋ฃจ์ ์ด ์ ์๊ฒ ์ถ์ต๋๋ค .
// next.config.js
const aliasPathsToResolve = [
{ name: 'components', path: path.resolve(__dirname, './components') },
{ name: 'Common', path: path.resolve(__dirname, '../../common/react/') },
]
module.exports = () => {
return {
webpack(config, { defaultLoaders }) {
config.module.rules.push({
test: /\.(js|jsx)$/,
include: [path.resolve(__dirname, '../../common/react/')],
use: [defaultLoaders.babel],
})
/** Resolve aliases */
aliasPathsToResolve.forEach((module) => {
config.resolve.alias[module.name] = module.path
})
}
}
}
์ด ๊ฒ์๋ฌผ์ ์์ฑํ๋ ์์ ์์ ์ต์ ๋ฒ์ ์ NextJ๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
@Lwdthe1 ์ฝ๋๋ฅผ ์๋ํ๋๋ฐ ์ฒ์์ ๋ค์ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค.
TypeError: Cannot read property 'then' of undefined
at getBaseWebpackConfig (/c2/wiz-frontend/packages/pipeline-view/node_modules/next/dist/build/webpack-config.js:85:25)
at async Promise.all (index 0)
at async HotReloader.start (/c2/wiz-frontend/packages/pipeline-view/node_modules/next/dist/server/hot-reloader.js:14:1675)
at async DevServer.prepare (/c2/wiz-frontend/packages/pipeline-view/node_modules/next/dist/server/next-dev-server.js:7:223)
at async /c2/wiz-frontend/packages/pipeline-view/node_modules/next/dist/cli/next-dev.js:22:359
์ฝ๊ฐ์ ์กฐ์ ์ ์ํํ๊ณ ๋ค์๊ณผ ๊ฐ์ด ๋๋์ต๋๋ค.
const path = require("path");
const libPath = "../components/src"
const aliasPathsToResolve = [
{ name: "Common", path: path.resolve(__dirname, libPath) }
];
module.exports = {
webpack: (config, { defaultLoaders }) => {
config.module.rules.push({
test: /\.(js|jsx)$/,
include: [path.resolve(__dirname, libPath)],
use: [defaultLoaders.babel]
});
/** Resolve aliases */
aliasPathsToResolve.forEach(module => {
config.resolve.alias[module.name] = module.path;
});
return config
}
};
๊ทธ๋ฌ๋ ๋ ๋ค๋ฅธ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค.
export { default as NavBar } from "./NavBar/NavBar"
^^^^^^
SyntaxError: Unexpected token 'export'
at wrapSafe (internal/modules/cjs/loader.js:1055:16)
at Module._compile (internal/modules/cjs/loader.js:1103:27)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1159:10)
....
์ด๊ฒ์ #2850๊ณผ #883์์ ์ ์ ์ง๋ฉดํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
๋ฐ๋ผ์ ์ ์ผํ ํด๊ฒฐ์ฑ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. https://github.com/martpie/next-transpile-modules#but -i-really-need-to-make-it-work-with-lerna
๋ด๊ฐ ๋ค์ ๋ฐ์ ๋ฐ๋ฅด๋ฉด Next.js๊ฐ ์ด ๋ฌธ์ ๋ฅผ ์ด๋ป๊ฒ ํด๊ฒฐํ ๊ณํ์ธ์ง ๊ณง RFC๊ฐ ๋ฐํ๋ ๊ฒ์ด์ง๋ง ๋๊ตฐ๊ฐ๊ฐ ์ง๊ธ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด์ผ ํ๋ ๊ฒฝ์ฐ https://github.com/ ์์ ๋ด ์๋ฃจ์ ์ npm์ ๊ฒ์ํ์ต๋๋ค.
"next": "npm:@sheerun/[email protected]",
next.config.js ๋ค์:
babelIncludeRegexes: [/turf/],
(์ ๊ฒฝ์ฐ์๋ ๋ชจ๋ ์๋ ํ์ผ์ babel๋ก ๋ฏธ๋ฆฌ ์ปดํ์ผํด์ผ ํ์ต๋๋ค)
์ด ๋ฌธ์ ์ ์ง์ ์ด ์์ต๋๊น?
next.js 9.2.0์ ์ฌ์ฉํ์ง๋ง babelIncludeRegexes
์ต์
์ด ์๋ํ์ง ์์ต๋๋ค.
์ด ๋ฌธ์ ์ ์ง์ ์ด ์์ต๋๊น?
next-transpile-modules
๋ ์ด ๋ฌธ์ ๋ฅผ ์ ํํ ํด๊ฒฐํ๋ ๊ฒ์ ๋ชฉํ๋ก ํฉ๋๋ค. ์๋ํด ๋ณด์
จ์ต๋๊น?
์๋ ํ์ธ์ @martpie ๋
์ด๋ฏธ ๋ด ๋ฌธ์ .babelrc ํ์ผ ํธ์ง์ ํด๊ฒฐํฉ๋๋ค. ๋๋ ์ด ๋ฌธ์ ๋ฅผ ์ฐธ์กฐ
๊ณ ๋ง์
@martpie next-transpile-modules
์์ง๋ง ์ฌ์ ํ ์์ฉ ํ๋ก๊ทธ๋จ์ ๋น๋ํ๋ ๋์ ์๋ ์ค๋ฅ์ ์ง๋ฉดํ๊ณ ์์ต๋๋ค. ๊ณต์ ์ฝ๋๋ฒ ์ด์ค์ ํจ๊ป monorepo๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. '@myapp/shared/components/componentname.js'์ ๊ฐ์ ๊ณต์ ์์ ๊ตฌ์ฑ ์์์ ์ก์ธ์คํ๋ ค๊ณ ํฉ๋๋ค. nextjs 9.x ๋ฐ ์ฌ์ฉ์ ์ ์ next.config.js
์์ต๋๋ค.
์ค๋ฅ
`
๋ชจ๋ ๊ตฌ๋ฌธ ๋ถ์ ์คํจ: ์๊ธฐ์น ์์ ํ ํฐ(12:4)
์ด ํ์ผ ์ ํ์ ์ฒ๋ฆฌํ๋ ค๋ฉด ์ ์ ํ ๋ก๋๊ฐ ํ์ํ ์ ์์ต๋๋ค. ํ์ฌ ์ด ํ์ผ์ ์ฒ๋ฆฌํ๋๋ก ๊ตฌ์ฑ๋ ๋ก๋๊ฐ ์์ต๋๋ค. https://webpack.js.org/concepts#loaders ์ฐธ์กฐ
| const ์คํผ๋ = ์ํ => {
| const renderDefaultSpinner = (์คํผ๋ ํด๋์ค, { ...๊ธฐํ }) => (
>
๋น๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค.
์ค๋ฅ: > ์นํฉ ์ค๋ฅ๋ก ์ธํด ๋น๋ ์คํจ
`
next.config.js
const withTM = require('next-transpile-modules')(['<strong i="26">@myapp</strong>']);
module.exports = withPlugins([withTM, withBundleAnalyzer], {
...
}
์ ๊ฐ ์ฌ๊ธฐ์ ๋ญ ์๋ชปํ๊ณ ์๋์ง ๋์์ฃผ์ธ์.
@raghav1086 ๋ฆฌํฌ์งํ ๋ฆฌ ์์ ๋ฌธ์ ๋ฅผ ์ด โโ์ ์์ต๋๊น? ;) ์ฌ๊ธฐ ์ฌ๋๋ค์ ์์์ ํผํ ๊ฒ์ ๋๋ค.
+1
๋ด ํ๋ก์ ํธ์ src/
๋๋ ํ ๋ฆฌ๊ฐ ์๊ณ ๋ช ๊ฐ์ง ๋ค๋ฅธ nextjs ์ฑ์์ ์ฌ์ฌ์ฉํ๋ ๋ช ๊ฐ์ง ๊ณตํต ์ ํธ๋ฆฌํฐ/๋ํผ๋ฅผ ๋ด๋ณด๋ด๋ ์คํํฐ ํ๋ ์์ํฌ์ ๋ํด lib/
๊ฐ ์์ต๋๋ค(๋ด ์์์ ).
dev ์๋ฒ๋ฅผ ์์ํ ๋ lib๊ฐ ์ธ์๋์ง ์์ต๋๋ค. lib/์ ๋ชจ๋ ๊ตฌ์ฑ ์์๋ ๋ก๋๋ฅผ ๊ฑฐ์น์ง ์๊ณ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
@Lwdthe1 ์ ๋ณํ๋ ์๋ฃจ์
(https://github.com/zeit/next.js/issues/706#issuecomment-569041997)์ ์ฌ์ฉํ์ฌ ์์ ๋ด ์๊ฒฌ์์ src ๋ฐ lib ๋ฌธ์ ๋ฅผ ์์ ํ์ต๋๋ค. aliasPathsToResolve
๋ฐฐ์ด์ ๋ฐ๋ณตํ๋ ๋์ config.resolve.modules
๋ฅผ ์ฌ์ฉํ๋ค๋ ์ ์ ์ ์ธํ๊ณ ๊ธฐ๋ณธ์ ์ผ๋ก ๋์ผํฉ๋๋ค.
webpack: (config, options) => {
config.resolve.modules = [
'./src/',
'./lib/',
'node_modules'
];
config.module.rules.push({
test: /\.(js|jsx)$/,
include: [path.resolve(__dirname, './lib/')],
use: [options.defaultLoaders.babel],
});
์์ฆ lerna, nextjs, babel์ ์๋ ์๋ฃจ์ ์ ๋ฌด์์ ๋๊น?
๊ฐ์ ธ์ค๊ธฐ ์ ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ฏธ๋ฆฌ ๋ณํํ์ง ์์ผ๋ ค๊ณ ๋ ธ๋ ฅํ๊ณ ์์ผ๋ฉฐ ์ฌ๊ธฐ์์ ๋ชจ๋ ์๋ฃจ์ ์ ์ฌ์ฉํ๋ ๋ฐ ์ด๋ ค์์ ๊ฒช์์ต๋๋ค. ๋ด๊ฐ ์ผํ ์์๋ ๊ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
next-transpile-modules
.next-babel-loader
include
๋ฐ exclude
๊ท์น์ ๊ฐ๊ฐ ํต๊ณผ/์คํจ๋ก ์
๋ฐ์ดํธํฉ๋๋ค.@mikestopcontinues next-transpile-modules
๋ TypeScript๋ฅผ ์ฌ์ฉํ์ฌ ์ฆ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
@calebmpeterson ๊ณผ @martpie (๋ณด๊ณ ๊ฐ๋๋ค! ๐). ๋ค์ ํ๋ฌ๊ทธ๋ก ๋์๊ฐ์ ๋ฌธ์ ๋ ํ์ ๋ชจ๋์ ์ฐธ์กฐํ ๋ฐฉ๋ฒ์ด ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ์๋ฅผ ๋ค์ด '@mono/components' ํจํด์ '@mono/components/Div' ๋ฑ์ ๊ฐ์ ธ์ค๊ธฐ๋ฅผ ์ง์ํ์ง ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ํจํด์ผ๋ก '@mono/components/Div'๋ฅผ ์ง์ ํด๋ ์๋ํ์ง ์์ต๋๋ค... ๋ชจ๋ ๊ณต์ ๊ตฌ์ฑ ์์์ ๋ํด ๊ทธ๋ ๊ฒ ํ๊ณ ์ถ์ง๋ ์์ต๋๋ค. ๋ํ ์ ๊ท์ ์์ฑ์ ๋ฆฌ๋ฒ์ค ์์ง๋์ด๋งํ์ฌ ์ผ์น ํจํด์ ์์ฑํ๋ ค๊ณ ์๋ํ์ผ๋ฉฐ ์ถ๋ ฅ ์ ๊ท์์ด ์๋ํ๋ ๋์ ๋ด๋ถ์์ ์๋ํ์ง ์๋ ๋ค๋ฅธ ์์ ์ด ์งํ๋๊ณ ์์ต๋๋ค.
์ด์์ ์ผ๋ก๋ ๋ชจ๋ ๊ฒ์ ์ฒ๋ฆฌํ๊ธฐ ์ํด '@mono'๋ฅผ ์ง์ ํ๊ณ , ๋ด package.json์ ๋ด ๊ฐ ์ฑ์ด ์์กดํ๋ ๋จ์ผ ์์ค ์์ค๋ก ๋จ๊ฒจ๋๊ณ ์ถ์ต๋๋ค. ๋ง์ฐฌ๊ฐ์ง๋ก ํ์ ๋ชจ๋์ ์ก์ธ์คํ ์ ์๋๋ก ๋ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ชจ๋ ๋จ์ผ ํญ๋ชฉ์ ๊ฐ์ ธ์ค๊ฑฐ๋ ๋ด๋ณด๋ด๋ ์ธ๋ฑ์ค ํ์ผ์ ์ ์ง ๊ด๋ฆฌํ๋ ๊ฒ์ ํผํ๊ณ ์ถ์ต๋๋ค.
๋์๊ฐ์ rootMode: 'upward'
ํตํด next-babel-loader
๋ฅผ ์ ๋ฌํ์ฌ babel์ด ํธ๋์คํ์ผ ๋
ผ๋ฆฌ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ค๋ฉด ํ์ฌ ๋ฌธ์ ๊ฐ ์์ ํ ํด๊ฒฐ๋ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ด์ฉ๋ฉด ์ด๊ฒ์ ๋ค๋ฅธ Next ๊ด๋ จ ๋ฌธ์ ๋ฅผ ์ด โโ์ ์์ง๋ง ๋ฌธ์ ์ ๊ทผ์์ Next๊ฐ webpack๊ณผ babel์ ์ฝํ ๋น์ ํ์ ์ธ ๋ฐฉ์์ธ ๊ฒ ๊ฐ์ต๋๋ค. ๋ฌผ๋ก babel-loader
๋ฅผ Next์ ์ถ๊ฐ ๋ก์ง๊ณผ ๋ณ๋๋ก ๋จ๊ฒจ๋๋ ๋ฐฉ๋ฒ์ด ์์๊น์?
next-transpile-modules
์ ๋ฉด์ ๋ํ ์
๋ฐ์ดํธ์
๋๋ค. ์ค๋ฅ๋ฅผ ์๋ชป ์ง๋จํ์ต๋๋ค. ์ฌ์ฉ์ ์ ์ .babelrc
๊ตฌ์ฑ์ด ํ์ํ ๊ฒฝ์ฐ ์ด ๋ฐฉ๋ฒ(์์ธ ๋๋ ํ์ ๋ชจ๋)์ ์ฌ์ฉํ์ฌ ๊ฐ์ ธ์ค๊ธฐ๊ฐ ์๋ํ์ง ์์ต๋๋ค. ์ฌ์ฉ์ ์ ์ ์ค์ ์ ํ์ํ ์ฝ๋์ ์ ์ฉ๋์ง ์์ต๋๋ค. ์ด๊ฒ์ ๋ค์ rootMode: 'upward'
๋ฌธ์ ์
๋๋ค.
@mikestopcontinues next-transpile-modules
์ ํจ๊ป babel.config.js
(global config)๋ฅผ ์ฌ์ฉํด์ผ ํ๋ฉฐ .babelrc
(local config)๊ฐ ์๋๋ผ FAQ์ ์ค๋ช
๋์ด ์์ต๋๋ค ;)
@martpie ๋ด๊ฐ ์ผ๋ง๋ ๋ถ๋๋ฌ์ด์ง
next-transpile-modules๊ฐ ๋๋ฅผ ์ํด React๋ฅผ ๊นจ๋จ๋ ธ์ต๋๋ค. 3๊ฐ์ ์์ ๋ชจ๋์ ํธ๋์คํ์ผํ๋ ๋์ ์๋ชป๋ ํํฌ๋ฅผ ์ฌ์ฉํ๋ค๋ ๋ฉ์์ง๊ฐ ํ์๋ฉ๋๋ค.
๋๊ตฐ๊ฐ๊ฐ ๊ฐ์ฅ ์ข์ ๊ตฌ์ฑ์ด ๋ฌด์์ธ์ง ๋ค์ ๋ฐ๋ณตํด์ ๋ฒ์ญ์ ์๋ํ๋๋ก ํ ์ ์์ต๋๊น? babel.config.js์ ์์ฑํด์ผ ํ๋ ๋ด์ฉ์ ์ดํดํ์ง ๋ชปํฉ๋๋ค.
@masbaehr ๋๋ถ๋ถ์ ๊ฒฝ์ฐ next.config ์ค์ ์ next-transpile-modules
๋ฅผ ์ถ๊ฐํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค.
์ ์ผํ ๋ฌธ์ ๋ next-transpile-modules
๊ฐ Yarn 2 pnp๋ฅผ ์ง์ํ์ง ์๋๋ค๋ ๊ฒ์
๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
next.js
๋ฅผ ๋ณธ๊ฒฉ์ ์ผ๋ก ์ฌ์ฉํ๊ณ ์ฃผ๋ณ์ ํ๋ถํ ๋ชจ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ตฌ์ถํ ์๋ก ์ด ๊ธฐ๋ฅ์ด ๋ ์ค์ํด์ง๋๋ค. ๋ด ๋ด๋ถ ๋ชจ๋์์ babel ์ปดํ์ผ ๋จ๊ณ๋ฅผ ๋ณต์ ํ๋ ์ค์ PITA๊ฐ ๋๊ณ ์์ต๋๋ค.๐๐ค