Next.js: CSS ํŒŒ์ผ์„ ๊ฐ€์ ธ ์˜ค์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

์— ๋งŒ๋“  2016๋…„ 12์›” 27์ผ  ยท  102์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: vercel/next.js

๋•Œ๋กœ๋Š” CSS๋ฅผ ๋ณ„๋„์˜ .css ํŒŒ์ผ๋กœ ๋‚˜๋ˆ„๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์„ ์‹œ๋„ํ–ˆ์Šต๋‹ˆ๋‹ค.

pages/
โ””โ”€โ”€ index
    โ”œโ”€โ”€ index.css
    โ”œโ”€โ”€ index.js
    โ””โ”€โ”€ component.js

๊ทธ๋Ÿฐ ๋‹ค์Œ index.js์—์„œ ๋‹ค์Œ์„ ์‹œ๋„ํ–ˆ์Šต๋‹ˆ๋‹ค.

import css from './index.css'

๊ทธ๋ฆฌ๊ณ  next.config.js์—์„œ :

module.exports = {
  webpack: function (config) {
    config.module.loaders = (config.module.loaders || []).concat({
      test: /\.css$/, loader: 'raw'
    })
    return config
  }
}

ํ•˜์ง€๋งŒ ์•ˆํƒ€๊น๊ฒŒ๋„ ๊ณ„์†ํ•ด์„œ ๋‹ค์Œ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

 ERROR  Failed to compile with 1 errors

This dependency was not found in node_modules:

* ./index.css

์–ด๋–ค ์ด์œ ๋กœ ๋“  ์˜ฌ๋ฐ”๋ฅธ ์œ„์น˜๋กœ ํ•ด๊ฒฐ๋˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ง€์—ญ component.js ๋Š” import component from './component.js' ๋ฅผ ํ†ตํ•ด ์ž‘๋™ํ•˜๋ฏ€๋กœ ์—ฌ๊ธฐ์„œ ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

๋‹ค์Œ์€ babel-plugin-inline-import๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ CSS ํŒŒ์ผ์„ ๊ฐ€์ ธ ์˜ค๋Š” ๊ฐ„๋‹จํ•œ ์†”๋ฃจ์…˜์ž…๋‹ˆ๋‹ค.

.babelrc

{
  "presets": ["next/babel"],
  "plugins": [
    [
      "inline-import",
      {
        "extensions": [".css"]
      }
    ]
  ]
}

ํŽ˜์ด์ง€ / ๊ตฌ์„ฑ ์š”์†Œ

import "prismjs";

import { PrismCode } from "react-prism";
import prismGlobalStyles from "prismjs/themes/prism.css";

export default () => {
    return (
        <div>
            <style global jsx>
                {prismGlobalStyles}
            </style>
            <PrismCode className="language-javascript">
                {`function(noop) {
                    return noop;
                }`}
            </PrismCode>
            {/* ... */}
        </div>
    );
};

๋ชจ๋“  102 ๋Œ“๊ธ€

์ด๊ฒƒ์€ ์„œ๋ฒ„์—์„œ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๊นŒ?
์•„์ง์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. cc @arunoda

์•„ ๋งž๋‹ค, ์ด๊ฒƒ์ด ์ž‘๋™ํ•˜๋ ค๋ฉด next.config.js์˜ webpack ๊ตฌ์„ฑ์ด ์–‘์ชฝ์—์„œ ์ž‘๋™ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

Next๊ฐ€ CSS ๋˜๋Š” SASS๋กœ ๋ฉ‹์ง€๊ฒŒ ํ”Œ๋ ˆ์ด ํ•  ์ˆ˜ ์—†๋‹ค๋Š” ์ ์—์„œ ๋น„์Šทํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ด ํŽ˜์ด์ง€๋กœ ๊ฐ€์ ธ ์˜ค๋Š” ํ‘œ์ค€ React ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ํฌํ•จ ๋œ components ๋””๋ ‰ํ† ๋ฆฌ๊ฐ€ ์žˆ์ง€๋งŒ SASS (๋˜๋Š” CSS) ํŒŒ์ผ๋กœ ๊ฐ€์ ธ ์˜ค๋ ค๊ณ  ํ•  ๋•Œ๋งˆ๋‹ค ~ "์ด ํŒŒ์ผ์— ์ ์ ˆํ•œ ๋กœ๋”๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค." ์œ ํ˜• ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€.

์ผ๋ฐ˜์ ์œผ๋กœ React์—์„œ ๋‚˜๋Š” SASS ํŒŒ์ผ์„ ๊ฐ€์ ธ์˜ค๊ณ  ์Šคํƒ€์ผ, CSS ๋ฐ sass ๋กœ๋”๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Webpack์„ ์ปดํŒŒ์ผํ•ฉ๋‹ˆ๋‹ค. next.config.js ํŒŒ์ผ์— ์ถ”๊ฐ€ํ•˜๋ ค๊ณ  ์‹œ๋„ํ–ˆ์ง€๋งŒ NPM์ด ์„ค์น˜ํ–ˆ์ง€๋งŒ ์—ฌ์ „ํžˆ ๋™์ผํ•œ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๊ฐ€ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

๋‚ด next.config.js ํŒŒ์ผ :

module.exports = {
  webpack: (config, { dev }) => {
    config.module.rules.push({ test: /\.scss$/, loader: ['style-loader', 'css-loader', 'sass-loader'] });
    return config;
  }
}

์ด ์งˆ๋ฌธ์ด ๋ฉ์ฒญํ•˜๊ฒŒ ๋“ค๋ฆฌ๊ฑฐ๋‚˜ ๊ทธ์— ๋Œ€ํ•œ ๋‹ต๋ณ€์„ ์„ค๋ช…ํ•˜๋Š” ๋ฌธ์„œ์—์„œ ๋ถ„๋ช…ํ•œ ๊ฒƒ์„ ๋†“์นœ ๊ฒฝ์šฐ ๋ฏธ์•ˆํ•˜์ง€๋งŒ, ๋ˆ„๊ตฐ๊ฐ€ SASS (๋˜๋Š” ์ตœ์†Œํ•œ CSS)๋ฅผ ๊ตฌ์„ฑ ์š”์†Œ ๋˜๋Š” ํŽ˜์ด์ง€๋กœ ๊ฐ€์ ธ ์˜ค๊ฑฐ๋‚˜ ์ปดํŒŒ์ผํ•˜๋Š” ์ž‘์—… ์˜ˆ์ œ๊ฐ€ ์žˆ๋‹ค๋ฉด ๋กœ๋“œ / ์ปดํŒŒ์ผํ•˜๊ธฐ ์œ„ํ•ด next.config.js ์— ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๊ฒƒ์ด ๋ฌด์—‡์ด๋“  ๋Œ€๋‹จํžˆ ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ฐ์‚ฌ!

css-modules-require-hook์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
CSS๊ฐ€ ์ž‘๋™ํ•˜๋„๋กํ•ฉ๋‹ˆ๋‹ค.

@spacedragon css-modules-require-hook์„ Next.js์™€ ํ†ตํ•ฉํ•˜๋Š” ๋ฐฉ๋ฒ•์˜ ์˜ˆ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ์ž‘๋™ํ•˜๋Š” ๋ฐ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ˆ„๊ตฐ๊ฐ€์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๋ฐํž ์ˆ˜ ์žˆ๊ฑฐ๋‚˜ Next ๋‚ด์—์„œ CSS ํŒŒ์ผ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค๋ฉด SASS๋ฅผ ์ปดํŒŒ์ผํ•˜๋Š” ๋ฐ ์—ฌ์ „ํžˆ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค (์ฝ”๋“œ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด).

README ํŒŒ์ผ์ด SVG ๋กœ๋” ์˜ˆ์ œ๋ฅผ ์ œ๊ฑฐํ•˜๋„๋ก ์—…๋ฐ์ดํŠธ๋˜์—ˆ์œผ๋ฉฐ SVG, CSS ๋ฐ SASS์™€ ๊ฐ™์€ ํŒŒ์ผ์— ๋Œ€ํ•œ ๋กœ๋”๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์€ ๊ถŒ์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ธ๋ผ์ธ CSS๊ฐ€ ์™œ ๊ดœ์ฐฎ์€์ง€๋Š” ๋ชจ๋ฅด๊ฒ ์ง€๋งŒ ๊ฐ€์ ธ์˜จ CSS๋Š” ๊ทธ๋ ‡์ง€ ์•Š์ง€๋งŒ ๊ทธ๋Ÿด๋งŒ ํ•œ ์ด์œ ๊ฐ€ ์žˆ๋‹ค๊ณ  ํ™•์‹ ํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ JS ์ •์˜ / ์ธ๋ผ์ธ CSS ๋ฐ SASS๋ฅผ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๋Š” ์ตœ์ƒ์˜ ์ „๋žต์— ๋Œ€ํ•ด ํ™•์‹ ์ด ์—†์Šต๋‹ˆ๋‹ค.

@MikeDigitize # 627 ๋ฐ # 638

์‹ค์ œ๋กœ ๊ฐ€๋Šฅํ•˜๊ณ  ์„œ๋ฒ„ ์ธก์—์„œ ์Šคํƒ€์ผ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ๋งค์šฐ ์‰ฝ์Šต๋‹ˆ๋‹ค.

๋…ธ๋“œ์—์„œ ์ง์ ‘ :

require.extensions['.css'] = function(file) {
    console.log(file.id)
    return;
}

๋ฐ”๋ฒจ ๋ ˆ์ง€์Šคํ„ฐ๋ฅผ ํ†ตํ•ด :

// from https://babeljs.io/docs/core-packages/babel-register/
require("babel-register")({
  // Optional ignore regex - if any filenames **do** match this regex then they
  // aren't compiled.
  ignore: /regex/,

  // Ignore can also be specified as a function.
  ignore: function(filename) {
    if (filename === '/path/to/es6-file.js') {
      return false;
    } else {
      return true;
    }
  },

  // Optional only regex - if any filenames **don't** match this regex then they
  // aren't compiled
  only: /my_es6_folder/,

  // Setting this will remove the currently hooked extensions of .es6, `.es`, `.jsx`
  // and .js so you'll have to add them back if you want them to be used again.
  extensions: [".es6", ".es", ".jsx", ".js"]
});

์›นํŒฉ ๋กœ๋”๋ฅผ ํ†ตํ•ด :

์„œ๋ฒ„์—์„œ ๋ Œ๋”๋งํ•˜๋Š” ๋™์•ˆ ์ค‘์š”ํ•œ CSS๋ฅผ ์ธ๋ผ์ธ ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๊ฐœ์ธ์ ์œผ๋กœ isomorphic-style-loader๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ•ซ ๋ฆฌ๋กœ๋”ฉ ๋ฐ ๊ธฐํƒ€ DX ๊ด€๋ จ ํ•ญ๋ชฉ๋„ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ํƒ€์‚ฌ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋ณต์žกํ•˜๊ณ  ์–ด๋–ป๊ฒŒ ๋“  CSS์—์„œ C๋ฅผ ์ œ๊ฑฐํ•˜๊ธฐ ๋•Œ๋ฌธ์— JS์—์„œ CSS์˜ ํŒฌ์ด ์•„๋‹™๋‹ˆ๋‹ค.

@viktorbezdek next.js ์™€ ํ•จ๊ป˜ isomorphic-style-loader๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ์‚ฌ์šฉ ํ–ˆ์Šต๋‹ˆ๊นŒ?

@noeljackson ์‹ค์ œ๋กœ๋Š” ์•„๋‹ˆ์ง€๋งŒ ๊ทธ๋ ‡๊ฒŒ ํ•  ์ƒ๊ฐ์ž…๋‹ˆ๋‹ค. Next.js๋Š” ์œ ๋ง ํ•ด ๋ณด์ด๋ฉฐ ์ž‘๋™ํ•˜๋ฉด ๋งŽ์€ ์‹œ๊ฐ„์„ ์ ˆ์•ฝ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ 1 ~ 2 ์ฃผ ๋‚ด์— ์กฐ์‚ฌํ•˜๊ณ  ์„ฑ๊ณตํ•˜๋ฉด ํ’€ ์š”์ฒญ์„ ์ œ์ถœํ•ฉ๋‹ˆ๋‹ค.

@viktorbezdek ์ œ๊ฐ€ ๊ฒ ์Šต๋‹ˆ๋‹ค . ๋‚˜๋Š” ๋‚ด๊ฐ€ ๋ฌด๋Šฅํ•˜์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์ง€๋งŒ ์ด๊ฒƒ์„ ์•Œ์•„๋‚ผ๋งŒํผ ๋ฐ”๋ฒจ ๋ณ€ํ™˜์„ ๋””๋ฒ„๊น…ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ดํ•ดํ•˜์ง€ ๋ชปํ•œ๋‹ค. ๋‚˜๋Š” ์ด๋Ÿฌํ•œ ์•„์ด๋””์–ด์˜ ์ˆœ์—ด์„ ์‹œ๋„ํ–ˆ์ง€๋งŒ ์•„๋ฌด๊ฒƒ๋„ 100 % ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. babel-plugin-webpack-loaders๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ ์ธ์ฝ”๋”ฉ ๋œ ์Šคํƒ€์ผ ์‹œํŠธ๋ฅผ ๊ฐ€์ ธ ์˜ค๋„๋ก raw-loader๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์—ˆ์ง€๋งŒ ์Šคํƒ€์ผ ๋กœ๋”๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋“ค์–ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! :) ๋งค์šฐ ๊ฐ์‚ฌ.

์ด๊ฒƒ์— ๋Œ€ํ•œ ํ•ด๊ฒฐ์ฑ…์ด ์žˆ์Šต๋‹ˆ๊นŒ? ์ „ ์„ธ๊ณ„์ ์œผ๋กœ CSS๋ฅผ ํฌํ•จ ํ•  ํ•„์š”๊ฐ€ ์—†๋„๋ก ์†”๋ฃจ์…˜์„๋ณด๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

FWIW, ๋ฐฉ๊ธˆ /static ํด๋”์— CSS ํŒŒ์ผ์„ ๋„ฃ์—ˆ์Šต๋‹ˆ๋‹ค. ์ข‹์€ ์ฝ” ๋กœ์ผ€์ด์…˜์€ ์•„๋‹ˆ์ง€๋งŒ ํฐ ๋ฌธ์ œ๋Š” ์•„๋‹™๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ์ฑ…์ด์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ๋๋‚ด์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๋Š” ์ตœ์ดˆ์˜ ํ”„๋กœํ†  ํƒ€์ž…์„ ๋กœ์ปฌ์—์„œ ๋งŒ๋“ค์—ˆ์ง€ ๋งŒ ์™„์„ฑํ•˜๋Š” ๋ฐ ๋ช‡ ์‹œ๊ฐ„์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ฃผ๋ง์ด ์ง€๋‚˜๋ฉด ๋๋‚  ๊ฑฐ๋ผ๊ณ  ํ™•์‹  ํ•ด์š”. ๊ณ„์† ์ง€์ผœ๋ด์ฃผ์„ธ์š”.

@matthewmueller CSS ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ?

@viktorbezdek ์ž‘์—… ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! CSS ๋ชจ๋“ˆ ์ง€์› (๋˜๋Š” ์œ ์‚ฌ)์€์ด ํ”„๋กœ์ ํŠธ IMO์— ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์Šคํƒ€์ผ์ด ์ง€์ •๋œ jsx๋Š” ๊ฐ„๋‹จํ•œ ์ƒํ™ฉ์—๋Š” ์ ํ•ฉํ•˜์ง€๋งŒ ์Šคํƒ€์ผ์ด ๋งŽ์€ ๊ตฌ์„ฑ ์š”์†Œ์—์„œ๋Š” ์ฝ๊ธฐ๊ฐ€ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

์ด์™€ ๊ฐ™์€ ๋ฐ”๋ฒจ ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์˜ต์…˜์ผ๊นŒ์š” (์„œ๋ฒ„ ์ธก๋„ ๋งˆ์ฐฌ๊ฐ€์ง€)? https://github.com/gajus/babel-plugin-react-css-modules

๋‚˜๋Š” ์ด๊ฒƒ์„ ์ž‘๋™ ์‹œํ‚ค๋ ค๊ณ  ๋…ธ๋ ฅํ–ˆ์ง€๋งŒ ์šด์ด ์—†๋‹ค : /

babel-plugin-css-modules-transform ์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋Š” CSS ๋ชจ๋“ˆ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ด ํฌํฌ ์—์„œ ๋‚ด ํ•ดํ‚ค ์˜ˆ์ œ๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

๋‹จ์ ์€ CSS๋ฅผ ๋ณ€๊ฒฝํ•  ๋•Œ๋งˆ๋‹ค ์„œ๋ฒ„๋ฅผ ์ข…๋ฃŒํ•˜๊ณ  ๋‹ค์‹œ ์‹œ์ž‘ํ•ด์•ผํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ผ๋ถ€ React ๊ตฌ์„ฑ ์š”์†Œ๋Š” import ๊ฐ€๋Šฅํ•œ ์ •์  ๋ฆฌ์†Œ์Šค๋ฅผ ํ†ตํ•ด ๊ธฐ๋ณธ ์Šคํƒ€์ผ์„ ๋…ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด https://github.com/react-component/slider ์˜ ๊ธฐ๋ณธ ์Šคํƒ€์ผ์„ ๊ฐ€์ ธ ์˜ค๋ ค๋ฉด ๋‹ค์Œ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

import 'rc-slider/assets/index.css';

static/ ๋””๋ ‰ํ„ฐ๋ฆฌ์—์ด ์Šคํƒ€์ผ ์‹œํŠธ๋ฅผ ๋ณต์‚ฌํ•˜์—ฌ ๋ถ™์—ฌ ๋„ฃ์„ ์ˆ˜๋Š” ์žˆ์ง€๋งŒ ํ–ฅํ›„ ๊ตฌ์„ฑ ์š”์†Œ ์—…๋ฐ์ดํŠธ์—์„œ ์—…์ŠคํŠธ๋ฆผ ์Šคํƒ€์ผ๊ณผ ๋™๊ธฐํ™”๋˜์ง€ ์•Š์œผ๋ฉฐ์ด ๊ตฌ์„ฑ ์š”์†Œ ์„ค๋ช…์„œ์—์„œ ๊ถŒ์žฅํ•˜๋Š” ๊ฒƒ๊ณผ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ๋Š” ์ด๋Ÿฌํ•œ CSS ํŒŒ์ผ์ด ์ „์—ญ ํšจ๊ณผ๋ฅผ ๋„์ž…ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. CSS๋ฅผ _capture_ํ•˜๊ณ  React ๋ผ์ดํ”„ ์‚ฌ์ดํด์— ๋„ฃ์–ด์„œ ๋งˆ์šดํŠธ ํ•ด์ œ, ์„œ๋ฒ„ ๋ Œ๋”๋ง ๋“ฑ์„ ์ˆ˜ํ–‰ ํ•  ์ˆ˜ ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.

๋งŽ์€ ๋„์„œ๊ด€์—์„œ ๊ทธ๋ ‡๊ฒŒํ•˜์ง€๋งŒ ์ข‹์€ ํŒจํ„ด์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

Zeit Next ๋‚ด๋ถ€์— ์ต์ˆ™ํ•˜์ง€ ์•Š์ง€๋งŒ import ์˜ ์ •์  ๋ถ„์„์„ ์‚ฌ์šฉํ•˜์—ฌ CSS๋ฅผ ๋“ฑ๋ก / ์บก์ฒ˜ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์šฐ๋ฆฌ๋Š” ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์ •๋ง ์ด์ƒ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. render() ์™ธ๋ถ€์—์žˆ๋Š” ๊ฒƒ๊ณผ ์œ ์‚ฌํ•˜๊ฒŒ ๊ตฌ์„ฑ ์š”์†Œ ์ˆ˜๋ช…์ฃผ๊ธฐ ๋‚ด์— ๋งˆ๋ฒ•์ฒ˜๋Ÿผ ์‚ฝ์ž…๋ฉ๋‹ˆ๋‹ค.

// ๋‹ค๋ฅธ ์‚ฌ๋žŒ๊ณผ ๊ณต์œ  ํ•  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ธ€์Ž„ ... ๋‚˜๋Š” CSS๋ฅผ ํ•ดํ‚นํ•˜๋Š” ๋ฐ ๋„ˆ๋ฌด ๋งŽ์€ ์‹œ๊ฐ„์„ ๋ณด๋ƒˆ์ง€ ๋งŒ (๋‚˜๋ฅผ ์œ„ํ•ด) ์ž‘๋™ํ•˜๋Š” ์†”๋ฃจ์…˜์— ๋„๋‹ฌํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก  ํ•ดํ‚น์ด์ง€๋งŒ ํ•ซ ๋ฆฌ๋กœ๋”ฉ์ด ์ž‘๋™ํ•˜๊ณ  ์„œ๋ฒ„ ์ธก ๊ตฌ์ถ•๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.

์ด gulpfile (https://gist.github.com/auser/25e88e39d83413773c01f4c000ec2806)๊ณผ ํ•จ๊ป˜ (_shudder_) gulp๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ชจ๋“  **/*.scss ํŒŒ์ผ์ด ํ•จ๊ป˜ ์—ฐ๊ฒฐ๋˜๊ณ  ๋‚ด๊ฐ€ ๋งˆ์šดํŠธํ•˜๋Š” Styles ๊ตฌ์„ฑ ์š”์†Œ๋กœ ๋ฐ€๋ ค๋‚ฉ๋‹ˆ๋‹ค. "์ผ๋ฐ˜"์š”์†Œ๋กœ ํŽ˜์ด์ง€.

๋‹ค์Œ์— ์ง„์ •ํ•œ postcss ์ง€์›์„๋ฐ›์„ ์ˆ˜์žˆ์„ ๋•Œ๊นŒ์ง€ ์ด๊ฒƒ์ด ๋‹ค๋ฅธ ์‚ฌ๋žŒ์—๊ฒŒ ๋„์›€์ด๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

@auser ํ•ดํ‚น

ํŽธ์ง‘ํ•˜๋‹ค:
Btw, gulpfile์— sass ํŒŒ์„œ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค!

์˜ˆ ๊ทธ๋ฆฌ๊ณ  ์•„๋‹ˆ์˜ค ... ์ €๋Š” ๋‹จ์ง€ .scss ํ™•์žฅ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ˆœ์ˆ˜ CSS ํŒŒ์ผ๊ณผ ๋ฏธ๋ฆฌ ์ปดํŒŒ์ผ ๋œ ํŒŒ์ผ์„ ๊ตฌ๋ณ„ํ•ฉ๋‹ˆ๋‹ค. postcss ( precss )๋Š” sass๋ฅผ ์ถฉ๋ถ„ํžˆ ๋ชจ๋ฐฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‚˜๋Š” ํ•˜๋‚˜๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. sass ํŒŒ์„œ๋กœ ์ž์œ ๋กญ๊ฒŒ ํŽธ์ง‘ํ•˜์‹ญ์‹œ์˜ค.

ํ˜„์žฌ๋กœ์„œ๋Š” gulp๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ css ํŒŒ์ผ์„ ์ปดํŒŒ์ผํ•˜๊ณ  ์ธ๋ผ์ธ์œผ๋กœ ๋นŒ๋“œํ•˜๊ฑฐ๋‚˜ ํ•ซ ๋ฆฌ๋กœ๋”ฉ์„ ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š๋Š” ๊ฒฝ์šฐ / static์—์„œ๋„ ์ตœ์ƒ์˜ ์†”๋ฃจ์…˜ ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

css import + hot reload๊ฐ€ ๊นจ๋—ํ•œ ๋ฐฉ์‹์œผ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. CSS๋Š” ๋ฌธ์ž์—ด๋กœ ๊ฐ€์ ธ์˜ค๊ณ  ์‚ฌ์šฉ์ž๋Š” ๋‹ค๋ฅธ ๋ฌธ์ž์—ด๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํŽ˜์ด์ง€์—์„œ์ด๋ฅผ ์ธ๋ผ์ธ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์˜ˆ์ œ๋ฅผ ๋ณด์‹œ๊ณ  ํ…Œ์ŠคํŠธ๋ฅผ ๋„์™€์ฃผ์„ธ์š”. PR์€ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค!

https://github.com/davibe/next.js-css-global-style-test

์ด ์˜ˆ์ œ๋Š” next.js ๊ณต์‹ ์˜ˆ์ œ๋กœ ๋งŒ๋“ค์–ด์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์Šต๋‹ˆ๊นŒ? @rauchg @arunoda @nkzawa (์ง์ ‘ ๊ด€๋ จ๋˜์ง€ ์•Š์€ ์‚ฌ๋žŒ์„ ํƒœ๊ทธํ•˜๋ฉด ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค)

@davibe ๋ฐ๋ชจ ๋ฐ babel-plugin-wrap-in-js์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

์˜ˆ์ œ์—์„œ CSS ํŒŒ์ผ๊ณผ SCSS ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด postcss ๋ฐ cssnext์—์„œ ์ž‘๋™ํ•˜๋Š”์ง€ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ?

@ khrome83 ์™œ ์•ˆ๋˜๋Š”์ง€ ๋ชจ๋ฅด๊ฒ ์ง€๋งŒ .babelrc ๋ฐ next.config.js๋ฅผ ์กฐ์ •ํ•˜๋Š” ๋ฌธ์ œ๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

@davibe ๊ตฌ์„ฑ์— ๋”ฐ๋ผ ๋‚ด ์•ฑ์„ ๋ฐฐํฌ ํ•  ์ˆ˜ ์—†์Œ์„ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค. ๋นŒ๋“œ๊ฐ€ .babelrc ํŒŒ์ผ์—์„œ next/babel ์„ ์ฝ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋ฌธ์ œ๋ฅผ ์ œ์ถœํ–ˆ์ง€๋งŒ์ด ๋ชจ๋“  ๊ฒƒ์—์„œ ํ•ด๊ฒฐ์ฑ…์ด ๋‚˜์˜ค๊ธฐ๋ฅผ ์ •๋ง ๊ธฐ๋Œ€ํ•ฉ๋‹ˆ๋‹ค. ์˜ ์šฉ์ด์„ฑ ๋ˆ„๋ฝ import file.css ์—์„œ create-react-app ,ํ•˜์ง€๋งŒ ๋‚œ ์•ž์œผ๋กœ ํ•ด๊ฒฐ์ฑ…์ด ์žˆ์–ด์•ผ ์•Œ๊ณ  :)

๋‚ด๊ฐ€ ์›ํ•˜๋Š” ์†”๋ฃจ์…˜์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

https://github.com/zeit/styled-jsx/pull/100#issuecomment -277133969

์šฐ๋ฆฌ ๋Š” .css ๊ฐ€์ ธ ์˜ค๊ธฐ๋ฅผ ์ง€์›ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (๋‹จ์ˆœํžˆ ๋ฌธ์ž์—ด์„ ๋‚ด๋ณด๋‚ด๋Š” ๋ชจ๋“ˆ๋กœ ํŠธ๋žœ์Šค ํŒŒ์ผํ•จ์œผ๋กœ์จ) (๊ทธ๋ฆฌ๊ณ  ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ˆœ์ˆ˜ ๋ฆฌ ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋กœ ํŠธ๋žœ์Šค ํŒŒ์ผํ•˜์—ฌ .svg ๋ฅผ ์ง€์›ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค)

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ .svg๋ฅผ ์ˆœ์ˆ˜ํ•œ ๋ฐ˜์‘ ๊ตฌ์„ฑ ์š”์†Œ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์ง€์›ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋งค์šฐ ๊ฐ„๋‹จํ•œ ํŠธ๋ฆญ์ž…๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ์—์„œ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ–ˆ๋Š”์ง€ ๋ณด์—ฌ์ฃผ๋Š” ๊ธฐ๋ณธ ์˜ˆ์ œ๋ฅผ ๋งŒ๋“ค๊ฒ ์Šต๋‹ˆ๋‹ค. =)

ํŽธ์ง‘ : https://github.com/zeit/next.js/pull/982 ์ฐธ์กฐ

@davibe ์ƒ˜ํ”Œ์„ ๊ธฐ๋ฐ˜์œผ๋กœ https://github.com/moxystudio/next.js-style-loader ๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด CSS ํŒŒ์ผ์„ next.js ํ”„๋กœ์ ํŠธ์— ์‰ฝ๊ฒŒ ์ถ”๊ฐ€ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ํƒ์ƒ‰ ํ•  ๋•Œ ์Šคํƒ€์ผ ์‹œํŠธ๋ฅผ ์ถ”๊ฐ€ / ์ œ๊ฑฐํ•œ๋‹ค๋Š” ์ ์—์„œ webpack์˜ style-loader ์™€ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค. SSR๋„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

css-loader (css ๋ชจ๋“ˆ ํฌํ•จ ๋ฐ ์ œ์™ธ), postcss-loader , sass-loader ๋ฐ ๊ธฐํƒ€ ๊ฐ€๋Šฅํ•˜๋ฉด ์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. css-loader๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ url ์˜ต์…˜์€ false beucase next.js ์ด๋ฏธ์ง€, ๊ธ€๊ผด ๋“ฑ์ด /static ๋˜์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ชจ๋“  ์ •๋ณด๋Š” README์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฆ๊ธฐ์‹œ๊ณ  ํ”ผ๋“œ๋ฐฑ์„์ฃผ์„ธ์š”!

repo์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค! CSS ํŒŒ์ผ์„ ๊ฐ€์ ธ ์˜ค๋Š” ๋ฐ ํšจ๊ณผ์ ์ด์—ˆ์Šต๋‹ˆ๋‹ค. blueprintjs๋ฅผ ์‹œ๋„ํ•˜๊ณ  ์žˆ๋Š”๋ฐ CSS๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ๋กœ๋“œ๋˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค! ๊ทธ๋Ÿฌ๋‚˜ CSS์— ํฌํ•จ ๋œ @ font-face ๊ทœ์น™์ด ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. :

--------------------ํŽธ์ง‘ํ•˜๋‹ค----------------------

์‹ค์ œ๋กœ ์ž‘๋™ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ ๊ธฐ๋ณธ์ ์œผ๋กœ nextjs ๋ผ์šฐํŒ…์€ / static / ์™ธ๋ถ€์—์„œ ์ •์  ์ฝ˜ํ…์ธ ๋ฅผ ์ œ๊ณต ํ•  ์ˆ˜ ์—†์œผ๋ฉฐ ์ƒ๋Œ€ ๊ฒฝ๋กœ๋กœ ์ธํ•ด ์‹ค์ œ๋กœ ํ—ˆ์šฉ๋˜์ง€ ์•Š๋Š” ๊ฒฝ๋กœ๋กœ๋กœ๋“œ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์•„์ด์ฝ˜์ด๋กœ๋“œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

@pencilcheck yes / static์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฒฝ๋กœ๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์•„๋งˆ๋„ README์—์„œ ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

fonts atm๊ณผ ๊ฐ™์€ CSS ํŒŒ์ผ์— ํฌํ•จ ๋œ ์ƒ๋Œ€ ๊ฒฝ๋กœ์™€ ๊ด€๋ จ๋œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ? ์•„๋‹ˆ๋ฉด ์ „์ฒด ๊ธ€๊ผด ํŒŒ์ผ๊ณผ CSS๋ฅผ ์ •์  ํด๋”์— ๋ณต์‚ฌํ•ด์•ผ ์ž‘๋™ํ•ฉ๋‹ˆ๊นŒ?

@pencilcheck ๋Š” CSS ํŒŒ์ผ์ด ์ •์  ์™ธ๋ถ€์—์žˆ์„ ์ˆ˜ /static/file ์ฐธ์กฐํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

์•Œ๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ npm ํŒจํ‚ค์ง€ ์ธ blueprint๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ node_modules ๋‚ด๋ถ€์˜ ํŒŒ์ผ์„ ์ˆ˜์ •ํ•  ํ•„์š”๊ฐ€ ์—†๋„๋กํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

@pencilcheck ๋ถˆํ–‰ํžˆ๋„ ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. next.js๋Š” ์ด๋ฏธ์ง€ ๋ฐ ๊ธฐํƒ€ ์ž์‚ฐ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๋งค์šฐ ์—„๊ฒฉํ•ฉ๋‹ˆ๋‹ค. ์ด ๋Œ€ํ™”๋ฅผ ๋”๋Ÿฝ ํžˆ์ง€ ๋ง๊ณ  ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ next-style-loader repo์—์„œ ๋ฌธ์ œ๋ฅผ ์ƒ์„ฑํ•˜์‹ญ์‹œ์˜ค.

@tgoldenberg ๋ฌธ์ œ๋ฅผ ๋” ์ž˜ ์„ค๋ช…ํ•˜๊ฑฐ๋‚˜ ์žฌํ˜„ ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค

@davibe , yarn ์ด์ƒ npm install yarn ์‚ฌ์šฉํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. Yarn์€ ์„ค๋ช… ํ•  ์ˆ˜์—†๋Š” ์˜ค๋ฅ˜๋ฅผ ๋˜์กŒ์ง€ ๋งŒ ์ผ๋‹จ ์ œ๊ฑฐํ•˜๋ฉด ์˜ˆ์ œ๊ฐ€ ํ”„๋กœ๋•์…˜์—์„œ ์ž˜ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ์ด๊ฒƒ์„ ์„ค์ •ํ•˜๋Š” ๋ฐ 4 ์‹œ๊ฐ„์„ ๋ณด๋ƒˆ๊ณ  ์‹œ๊ฐ„์„ ์ ˆ์•ฝํ•˜๋ ค๋Š” ๋ชจ๋“  ์‚ฌ๋žŒ์—๊ฒŒ ๊ด€์‹ฌ์ด์žˆ์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ ์˜ˆ์ œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ณ€๊ฒฝ์‹œ ์Šคํƒ€์ผ์„ ์ž๋™์œผ๋กœ ์ ์šฉํ•˜๊ณ  PostCSS๋ฅผ ํ†ตํ•ด CSS๋ฅผ ์‹คํ–‰ํ•˜๋ฉฐ css-loader ์—์„œ ๋กœ์ปฌ ๋ชจ๋“ˆ ์ด๋ฆ„์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ํ›„์ž์˜ ๋ถ€์žฌ๋Š” "๊ธ€๋กœ๋ฒŒ css"/ "css ์ˆ˜์ž…"์˜ˆ์ œ์˜ ํ˜„์žฌ ์ƒํƒœ์—์„œ ์ €์—๊ฒŒ ์ฃผ์š” ๊ฑฐ๋ž˜ ์ค‘๋‹จ ์š”์ธ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

component.js

import React from 'react';
import stylesheet from './styles.css';

const [css, className] = stylesheet;
const Component = () => (
    <p className={className.paragraph}>
        <Head><style dangerouslySetInnerHTML={{__html: css}} /></Head>
        bazinga
    </p>
);

.babelrc

{
    "presets": [
        "next/babel"
    ],
    "plugins": [
        ["wrap-in-js", {
            "extensions": ["css$"]
        }]
    ]
}

next.config.js
exports-loader ์˜ ๋†€๋ผ์šด ํ•ดํ‚น์— ์ฃผ๋ชฉํ•˜์„ธ์š”. ๋” ๋‚˜์€ ๋ฐฉ๋ฒ•์ด ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ํ™•์‹คํžˆ ???

module.exports = {
    webpack: (config) => {
        config.module.rules.push(
            {
                test: /\.css$/,
                use: [
                    {
                        loader: 'emit-file-loader',
                        options: {
                            name: 'dist/[path][name].[ext]'
                        }
                    },
                    {
                        loader: 'raw-loader'
                    },
                    {
                        loader: 'val-loader'
                    },
                    {
                        loader: 'exports-loader',
                        options: {
                            0: 'exports[0][1]',
                            1: 'exports.locals'
                        }
                    },
                    {
                        loader: 'css-loader',
                        options: {
                            modules: true,
                            minimize: true
                        }
                    },
                    {
                        loader: 'postcss-loader'
                    }
                ]
            }
        );

        return config;
    }
};

์ €๋Š” @satazor ๊ฐ€ ์Šค๋ ˆ๋“œ์—์„œ ๋” ๋†’์€ ๋ƒˆ์Šต๋‹ˆ๋‹ค : https://github.com/jozanza/next-css-json-loader.

next.config.js ๋ช‡ ์ค„๋งŒ ์ถ”๊ฐ€ํ•˜๋ฉด๋ฉ๋‹ˆ๋‹ค.

module.exports = {
  webpack: config => {
    config.module.rules.push({
      test: /\.css$/,
      loader: 'emit-file-loader',
      options: {
        name: 'dist/[path][name].[ext]',
      }
    }, {
      test: /\.css$/,
      loader: 'babel-loader!next-css-json-loader',
    });
    return config;
  },
};

์Šคํƒ€์ผ์€ js ๊ฐ์ฒด๋กœ ๊ฐ€์ ธ ์˜ค๋ฏ€๋กœ glamor ๋ฐ ์œ ์‚ฌํ•œ ์†”๋ฃจ์…˜๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ธฐ๊ฐ€ ๋งค์šฐ ์‰ฝ์Šต๋‹ˆ๋‹ค.

// .css files now conveniently expose all styles as js objects
import styles from 'some-package/styles.css';
import { css } from 'glamor';
// ...
<div {...css(styles)}>
  this is a nice box. 
</div>

๊ฑด๋ฐฐ! ๐Ÿป :)

๋งˆํฌ ๋‹ค์šด ํŒŒ์ผ์„ ๋ฌธ์ž์—ด๋กœ ๊ฐ€์ ธ ์˜ค๋Š” ๋ฐ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ? ํ˜„์žฌ ์›์‹œ ๋กœ๋”๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์ง€๋งŒ ์›นํŒฉ ํ”Œ๋Ÿฌ๊ทธ์ธ์ด๋ฏ€๋กœ ์„œ๋ฒ„์—์„œ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ฟก ๋นต๋€จ

๋ฐฉ๊ธˆ markdown ๊ฐ€์ ธ ์˜ค๊ธฐ๋ฅผ ์œ„ํ•ด babel ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ์€ ๋‚ด ๋ชจ๋ฐ”์ผ์—์„œ ๋‚ด GitHub๋ฅผ ๋ณด๋ฉด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@ khrome83 ๊ต‰์žฅํ•œ ์†Œ๋ฆฌ. ๊ทธ๊ฒƒ์„ ์‹œ๋„ํ•˜๊ธฐ๋ฅผ ๊ธฐ๋Œ€

@ khrome83 ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! ๋‚ด๊ฐ€ ํ•œ๋ฒˆํ•ด๋ณผ ๊ฒŒ

์ด ์ž‘์—…์„ ์ •๋ง ๋นจ๋ฆฌํ•ด์•ผํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— readme๋ฅผ ์—…๋ฐ์ดํŠธํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ฐ”๋ฒจ ํ”Œ๋Ÿฌ๊ทธ์ธ์œผ๋กœ ํฌํ•จํ•˜๊ณ 

'File.md'์—์„œ ํŒŒ์ผ ๊ฐ€์ ธ ์˜ค๊ธฐ;

๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ์ผํ–ˆ๋‹ค, ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! ๋งค์šฐ ๋„์›€์ด ๋จ

์ด๊ฒƒ์€ ์ฃผ์ œ์—์„œ ๋ฒ—์–ด๋‚œ ๊ฒƒ์ด์ง€๋งŒ ๋ฌธ์ œ๊ฐ€ ์ข…๊ฒฐ๋˜์—ˆ์œผ๋ฏ€๋กœ ์ž์œ ๋กญ๊ฒŒ ์ž์„ธํžˆ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. :)

๋งˆํฌ ๋‹ค์šด์˜ ๊ฒฝ์šฐ ์ˆ˜ํ–‰ ํ•  ์ˆ˜์žˆ๋Š” ์ž‘์—…์€ ๋‘ ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.

(1)
ํ•˜๋‚˜๋Š” ๋งˆํฌ ๋‹ค์šด ํŒŒ์ผ์„ ๋ฌธ์ž์—ด๋กœ ํฌํ•จ์‹œํ‚จ ๋‹ค์Œ ๋Ÿฐํƒ€์ž„์— html / react๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. css์— ๋Œ€ํ•œ next.js ์˜ˆ์ œ examples/with-globa-stylesheet/.babelrc ์—์„œ ์‚ฌ์šฉ ๋œ ๊ฒƒ์ฒ˜๋Ÿผ ์ผ๋ฐ˜ wrap-in-js babel ๋กœ๋” ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋งˆํฌ ๋‹ค์šด ํŒŒ์ผ ํ™•์žฅ์ž์— ๋“ฑ๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

(2)
๋‹น์‹ ์ด ํ•  ์ˆ˜์žˆ๋Š” ๋˜ ๋‹ค๋ฅธ ์ผ์€ markdown-in-js๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŠธ๋žœ์Šค ํŒŒ์ผ์‹œ ๋งˆํฌ ๋‹ค์šด์„ ๋ฒˆ์—ญํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๋งˆํฌ ๋‹ค์šด ๋ฌธ์„œ๊ฐ€ ์ด๋ฏธ ๋ฏธ๋ฆฌ ๋ Œ๋”๋ง๋˜์—ˆ์œผ๋ฏ€๋กœ ๋Ÿฐํƒ€์ž„์— ๋” ๋น ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์ผ๋ถ€ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ๋” ํฅ๋ฏธ๋กœ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (js ๋งŒ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค). ๋˜ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์‚ฌ์šฉ์ž ์ง€์ • React ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฝ์ž… ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ถˆํ–‰ํžˆ๋„์ด ๊ฒฝ์šฐ source.js ๊ณผ ๊ฐ™์ด ๋งˆํฌ ๋‹ค์šด์„ ์ธ๋ผ์ธ์œผ๋กœ ์ž‘์„ฑํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

(2)๋ฅผ ์„ ํƒํ•˜๋ฉด markdown-in-js ๊ตฌ๋ฌธ์— ๋Œ€ํ•œ ๊ตฌ๋ฌธ hilight๋ฅผ ์ œ๊ณตํ•˜๋Š” atom ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์žˆ์œผ๋ฉฐ language-markdown-in-js

@davibe ํŒ ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! ๋‚˜๋Š” markdown์„ ๋นŒ๋“œ ์‹œ๊ฐ„์œผ๋กœ ๊ตฌ๋ฌธ ๋ถ„์„ํ•˜๊ณ  ์‹ถ์ง€๋งŒ markdown-in-js์— ๋Œ€ํ•œ ์œ ์ผํ•œ ๋ฌธ์ œ๋Š” ์ž‘์„ฑํ•˜๋Š” ๋™์•ˆ ๋ฐฑํ‹ฑ์„ ์ด์Šค์ผ€์ดํ”„ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ?

๋ฟก ๋นต๋€จ

๊ทธ๋…€์˜ ๋งˆํฌ ๋‹ค์šด ๋ Œ๋”๋ง์ด ์žˆ์Šต๋‹ˆ๋‹ค. ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ž‘์„ฑํ•œ ์ด์œ ๋„ ๋˜‘๊ฐ™์Šต๋‹ˆ๋‹ค. ๋งˆํฌ ๋‹ค์šด์„ ๋ฌธ์ž์—ด๋กœ ๋Œ์–ด์˜จ ๋‹ค์Œ react-markdown์„ ํ†ตํ•ด ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ๋ชฉ๋ก์„ ์ฒ˜๋ฆฌํ•˜๋Š” List ๊ตฌ์„ฑ ์š”์†Œ์™€ ๊ฐ™์ด ๋งˆํฌ ๋‹ค์šด ๋ Œ๋” ์กฐ๊ฐ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฐ˜์‘ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์€ ์ ์  ๋” ์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. Styled JSX์™€ ์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์— ๋Œ€ํ•œ ์—…๋ฐ์ดํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ์œ„์˜ ์˜๊ฒฌ์„ ํ†ตํ•ด ํ˜„์žฌ ์™„๋ฒฝํ•œ ์†”๋ฃจ์…˜์ด ์—†์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์•„๋ฃจ
isomorphic-style-loader- https: //www.npmjs.com/package/isomorphic-style-loader๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์˜ˆ์ œ๋ฅผ ๊ฐ€์งˆ ์ˆ˜

๊ทธ๊ฑฐ ์ •๋ง ์™„๋ฒฝ ํ• ๊ฒƒ ๊ฐ™์•„!

.css ๋˜๋Š” .scss ํŒŒ์ผ์„ ์ฐจ๋ก€๋กœ ๊ฐ€์ ธ ์˜ค๋Š” npm ํŒจํ‚ค์ง€์—์„œ ๋ฐ˜์‘ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๊ฐ€์ ธ์˜ฌ ๋•Œ ํ•ด๊ฒฐ์ฑ…์ด ์žˆ์Šต๋‹ˆ๊นŒ? ๊ธฐ๋ณธ์ ์œผ๋กœ node_modules์—์„œ ๊ฐ€์ ธ์˜จ ํŒŒ์ผ์„ ํŠธ๋žœ์Šค ํŒŒ์ผ

๋ช‡ ์ฃผ ๋™์•ˆ CRA (Create-React-App)๋ฅผ ์‚ฌ์šฉํ•ด ์™”์ง€๋งŒ ์˜ค๋Š˜์€ Next.js๋ฅผ ์ ‘ํ–ˆ๊ณ  CRA๊ฐ€ ํ˜„์žฌ ์„œ๋ฒ„ ์ธก ๋ Œ๋”๋ง (SSR)์„ ์ง€์›ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ •๋ง ๋ถ€๋„๋Ÿฌ ์› ์Šต๋‹ˆ๋‹ค.
๊ธฐ๋ณธ์ ์œผ๋กœ SSR ์ง€์›์„ ์œ„ํ•ด Next.js๋กœ ์ „ํ™˜ํ•˜๊ณ  ์‹ถ์ง€๋งŒ .scss ํŒŒ์ผ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜์—†๋Š” ๊ฒƒ์€ ์ €๋ฅผ ๋ฐฉํ•ดํ•ฉ๋‹ˆ๋‹ค.
Webpack ๊ตฌ์„ฑ์— SASS ๋กœ๋”๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ฐพ์€ ์‚ฌ๋žŒ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

cr101์— ๋™์˜ํ•˜๊ณ  CSS / SASS์— ๋Œ€ํ•œ ์ง€์›์ด ์—†๋‹ค๋Š” ๊ฒƒ์€ ๋‚˜์—๊ฒŒ ์˜ต์…˜์ด ์•„๋‹Œ ๊ธฐ์ดˆ์™€ ๊ฐ™์€ CSS ํ”„๋ ˆ์ž„ ์›Œํฌ๋ฅผ ๋ฒ„๋ ค์•ผํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

@davibe์—์„œ ์ œ๊ณตํ•˜๋Š” ์ €์žฅ์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์—ˆ์ง€๋งŒ ๊ทธ๋Š” ๋” ์ด์ƒ ์œ ์ง€ ๊ด€๋ฆฌํ•˜์ง€ ์•Š์œผ๋ฉฐ ์ตœ์‹  ๋นŒ๋“œ ๊ฐ€ ๊ทธ๊ฐ€ ๋ณด์œ ํ•œ ์†”๋ฃจ์…˜์œผ๋กœ ์ค‘๋‹จ๋ฉ๋‹ˆ๋‹ค .

๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ์ด๊ฒƒ์— ๋Œ€ํ•œ ํ•ด๊ฒฐ์ฑ…์„ ์ฐพ์•˜๋‹ค๋ฉด ์ข‹์•„ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. 2.4.1๋กœ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๊ฒƒ์€ ๋ณด์•ˆ ๋ฒ„๊ทธ๋กœ ์ธํ•ด ์ ˆ๋Œ€์ ์œผ๋กœ ํ•„์š”ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์‹œ ๋‚ด๋ ค๊ฐˆ ์ˆ˜์žˆ๋Š” ์˜ต์…˜์ด ์—†์Šต๋‹ˆ๋‹ค.

@Yuripetusko @ cr101 @tgoldenberg ์ ˆ๋Œ€์ ์œผ๋กœ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ์†”์งํžˆ ๋‹ค์Œ์€ ์ƒ์ž์—์„œ ๋ฒ—์–ด๋‚œ ์ผ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด ์ •๋ง ๋Œ€๋‹จํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ํ•˜๋“œ ์ฝ”๋”ฉ ๋œ ๊ตฌ์กฐ (ํ•„์ˆ˜ /pages ๋””๋ ‰ํ† ๋ฆฌ, /static ๋“ฑ)๋„ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์™„์ „ํžˆ ์ง€์›๋˜์ง€ ์•Š๋Š” scss ๋ชจ๋“ˆ์€ ์šฐ๋ฆฌ์—๊ฒŒ ๋ชจ๋“  ๊ฒƒ์„ ๋ง๊ฐ€ ๋œจ๋ฆฝ๋‹ˆ๋‹ค. ์ž๋™ ์ค‘๋‹จ ์ ๊ณผ ๋ชจ๋“  ํ•ญ๋ชฉ์˜ ์ข…ํšก๋น„ ์žฌ ๊ณ„์‚ฐ์ด ํฌํ•จ ๋œ ๋งค์šฐ ๋ณต์žกํ•œ scss ๊ตฌ์กฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๊ตฌ์กฐ๋ฅผ ์™„๋ฒฝํ•˜๊ฒŒ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์—ด์‹ฌํžˆ ๋…ธ๋ ฅํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์€ ์šฐ๋ฆฌ๊ฐ€ ์กด์žฌํ•˜๋Š” ์ˆœ๊ฐ„์— ๊ฐ€์ง€๊ณ ์žˆ๋Š” ๋ชจ๋“  scss ๋ฌผ๊ฑด์„ ๋ฒ„๋ฆด ์ˆ˜ ์—†๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ์ง€์›๋˜์ง€ ์•Š๋Š” scss ๋Š”์ด ์•„๋ฆ„๋‹ค์šด ๋„๊ตฌ๋กœ์˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ๋ง‰๋Š” ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์ด์ง€๋งŒ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์‚ฌ์‹ค # 1615-์ง„ํ–‰์ค‘์ธ ์ž‘์—…์ด ์žˆ์Šต๋‹ˆ๋‹ค. @timmywil ์ด next ๊ณผ (์™€) ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋„๋ก isomorphic-style-loader ์„ (๋ฅผ) ์„ค์ •ํ•˜๋ ค๊ณ ํ•ฉ๋‹ˆ๋‹ค. ๊ด€์‹ฌ์žˆ๋Š” ๋ชจ๋“  ์‚ฌ๋žŒ์ด ๊ฐ€์ž…ํ•˜๊ณ  ์ฐธ์—ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์Šค๋ ˆ๋“œ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ชจ๋“  ์†”๋ฃจ์…˜์„ ์‹œ๋„ํ–ˆ์ง€๋งŒ ๊ทธ์ค‘ ํ•˜๋‚˜๋ฅผ ์ž‘๋™์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ €๋Š” ์ œ ์ž์‹ ์˜ ์‹œ๋„๋ฅผํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ๊ณ  ์—ฌ๊ธฐ์— ๊ทธ๊ฒƒ์„ ๋ฌธ์„œํ™”ํ–ˆ์Šต๋‹ˆ๋‹ค

@almeynman ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! ํ™•์‹คํžˆ ๋‹น์‹ ์˜ ์ ‘๊ทผ ๋ฐฉ์‹์„ ๋ณผ ๊ฒƒ์ž…๋‹ˆ๋‹ค!
๊ทธ๊ฑด ๊ทธ๋ ‡๊ณ , ๋‚˜๋Š” ์ด ์˜ˆ์ œ์— ๋”ฐ๋ผ scss ๋ชจ๋“ˆ์ด ์ž‘๋™ํ•˜๋„๋ก ๊ด€๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ํ•œ ๊ฒƒ์€ sass-loader ํ•˜๊ณ  ์†Œ์Šค ๋งต์„ ํ™œ์„ฑํ™”ํ•˜๋Š” ๊ฒƒ๋ฟ์ž…๋‹ˆ๋‹ค.

์ด๋Ÿฐ ์‹์œผ๋กœ next.js ์ง€์› CSS (์‹ฌ์ง€์–ด SCSS)๋ฅผ ๋งŒ๋“ค ์ˆ˜์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

๋จผ์ € next.config.js ์—์„œ ์ฃผ์–ด์ง„ ๋กœ๋”์™€ DefintPlugin ์ธ์Šคํ„ด์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ์›นํŒฉ ๊ตฌ์„ฑ์„ ์กฐ์ •ํ•ฉ๋‹ˆ๋‹ค.

const webpack = require('webpack');

module.exports = {
  webpack: (config, {dev}) => {
    config.module.rules.push({
      test: /\.scss$/,
      use: [
        'style-loader',
        'css-loader',
        'sass-loader'
      ],
      exclude: /node_modules/,
    });

    config.plugins.push(
      new webpack.DefinePlugin({
        "process.env": {
          // flag to indicate this is for browser-side
          BROWSER: JSON.stringify(true),
       }
      })
    );

    return config;
  }
};

๊ทธ๋Ÿฐ ๋‹ค์Œ ๊ตฌ์„ฑ ์š”์†Œ ์ฝ”๋“œ์—์„œ ์กฐ๊ฑด์ด์žˆ๋Š” ์Šคํƒ€์ผ ํŒŒ์ผ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋ธŒ๋ผ์šฐ์ € ์ธก ๋ฒˆ๋“ค๋ง์—๋งŒ ์Šคํƒ€์ผ ๋ชจ๋“ˆ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

if (process.env.BROWSER) {
  require("./style.scss");
}

if (process.env.BROWSER) ๊ดœ์ฐฎ๋‹ค๋ฉด ์™„๋ฒฝํ•˜๊ฒŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

์ข‹์€ ์ ‘๊ทผ ๋ฐฉ์‹์ด ์—ฌ๊ธฐ ์žˆ์Šต๋‹ˆ๋‹ค

@almeynman IMO๋Š” ํ•ด๋‹น ํŽ˜์ด์ง€์™€ ๊ด€๋ จ๋œ CSS ์Šคํƒ€์ผ ๋งŒ๋กœ๋“œํ•˜๋Š” ๋Œ€์‹  ๋ชจ๋“  ํŽ˜์ด์ง€์—์„œ ์ „์ฒด ์›น ์‚ฌ์ดํŠธ์— ๋Œ€ํ•œ CSS ์ฝ”๋“œ๋ฅผ๋กœ๋“œํ•˜๋ฏ€๋กœ ๊ทธ๋ฆฌ ์ข‹์€ ์ ‘๊ทผ ๋ฐฉ์‹์€ ์•„๋‹™๋‹ˆ๋‹ค.
์ „์ฒด ์›น ์‚ฌ์ดํŠธ์— CSS ๋Œ€์‹  ํ•„์š”ํ•œ .scss ํŒŒ์ผ ๋งŒ ๊ฐ€์ ธ ์˜ค๋ฉด ํ•„์š”ํ•œ CSS ์ฝ”๋“œ ๋งŒ๋กœ๋“œํ•˜์—ฌ ํŽ˜์ด์ง€ ํฌ๊ธฐ๋ฅผ ํฌ๊ฒŒ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@ cr101 ์•ˆ๋…•ํ•˜์„ธ์š”, ์ €๋Š” ๋ชฐ๋ž์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ ์„ค์ •์„ ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜์œผ๋ฉฐ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์„ ์œ„ํ•ด ์ฐธ์กฐํ•˜๊ธฐ ์œ„ํ•ด ๊ฒŒ์‹œํ–ˆ์Šต๋‹ˆ๋‹ค (๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ์ข‹๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค ...). ๋‚˜๋Š” ์—ฌ์ „ํžˆ ๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๋ฌผ์— ์„ค๋ช… ๋œ ๋‚ด ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ์„ค์ •์— ๋Œ€ํ•œ ํ”ผ๋“œ๋ฐฑ์„ ์ฃผ์‹œ๋ฉด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ด€์‹ฌ์ด ์žˆ๋‹ค๋ฉด ๋” ๋งŽ์€ ์˜ˆ์™€ ํ† ๋ก  :

https://github.com/iaincollins/nextjs-starter
https://github.com/zeit/next.js/issues/2534
https://github.com/zeit/next.js/tree/v3-beta/examples/with-global-stylesheet

์œ„์™€์ด ์Šค๋ ˆ๋“œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ PostCSS๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ณ€ํ™˜ ํ•  ์ˆ˜์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

  • ์ „์—ญ SCSS ํŒŒ์ผ (๋ชจ๋“ˆ์€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กœ๋•์…˜์„ ์œ„ํ•ด ๋ชจ๋“  CSS๋ฅผ ์‚ฌ์ „ ์ปดํŒŒ์ผํ•˜๋ ค๋ฉด ์ง„์ž… ์ ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค).
  • ์ƒ๋Œ€ URL์„ ํ†ตํ•ด ์ฐธ์กฐ๋˜๋Š” ์‚ฌ์šฉ์ž ์ง€์ • ๊ธ€๊ผด๋กœ ํƒ€์‚ฌ CSS๋ฅผ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค (์ธ๋ผ์ธ ๋งค์ง์„ ํ†ตํ•ด ํ•ด๊ฒฐ๋จ).

/static/styles/app.css ์—์žˆ๋Š” ๋‹จ์ผ CSS ํŒŒ์ผ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ํ•ซ ๋ฆฌ๋กœ๋”ฉ์ด ์—ฌ์ „ํžˆ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. styled-jsx ์˜ ์‚ฌ์šฉ๋ฒ•์— ์œ ์˜ํ•˜์‹ญ์‹œ์˜ค. ๊ทธ๋Ÿฌ๋‚˜ <style dangerouslySetInnerHTML={} /> ์‚ฌ์šฉํ•˜์—ฌ ์—†์ด๋„ ์ˆ˜ํ–‰ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

postcss.config.js

module.exports = {
  plugins: [
    require("postcss-easy-import")({ prefix: "_" }), // keep this first
    require("postcss-url")({ url: "inline" })
  ]
};

next.config.js

ํ•ซ ๋ฆฌ๋กœ๋“œ๋ฅผ ์œ„ํ•ด dev ๋ชจ๋“œ์—์„œ .scss๋ฅผ ๋ณ€ํ™˜ํ•˜๊ณ  prod์˜ ๋‹จ์ผ .css ํŒŒ์ผ๋กœ ์ถ”์ถœํ•˜๋Š” ๋กœ๋”. ์ด๊ฒƒ์€ ๋‚˜์—๊ฒŒ build/app.css ํ•˜๋ฏ€๋กœ Production ๋นŒ๋“œ์—์„œ cp build/app.css static/styles/app.css ๋’ค์— next build ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ์ •์  ๋‚ด๋ณด๋‚ด๊ธฐ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋กํ•˜๊ณ  ์•„๋ž˜์™€ ๊ฐ™์ด ์‚ฌ์šฉ์ž ์ง€์ • ํ—ค๋”์— ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

const ExtractTextPlugin = require('extract-text-webpack-plugin');

export default {
  webpack: (config, { dev }) => ({
    ...config,
    module: {
      ...config.module,
      rules: [
        ...config.module.rules,
        {
          test: /\.(css|scss)/,
          loader: 'emit-file-loader',
          options: {
            name: 'dist/[path][name].[ext]'
          }
        },
        ...(dev
          ? [
              {
                test: /\.css$/,
                use: ['raw-loader', 'postcss-loader']
              },
              {
                test: /\.s(a|c)ss$/,
                use: [
                  'raw-loader',
                  {
                    loader: 'postcss-loader',
                    options: {
                      sourceMap: true
                    }
                  },
                  {
                    loader: 'sass-loader',
                    options: {
                      sourceMap: true
                    }                    
                  }
                ]
              }
            ]
          : [
              {
                test: /\.(css|scss)/,
                use: ExtractTextPlugin.extract({
                  use: [
                    {
                      loader: 'css-loader',
                      options: {
                        importLoaders: 2,
                        modules: false,
                        url: true,
                        minimize: true,
                        localIdentName: '[hash:base64:5]'
                      }
                    },
                    {
                      loader: 'postcss-loader'
                    },
                    {
                      loader: 'sass-loader'
                    }
                  ]
                })
              }
            ]),
        {
          test: /\.(ico|jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2)(\?.*)?$/,
          loader: 'url-loader?limit=100000&&name=[name].[ext]?[hash:8]'
        }
      ]
    },
    plugins: [
      ...config.plugins,
      ...(dev ? [] : [new ExtractTextPlugin('app.css')])
    ]
  }),
};

๋งž์ถค ํ—ค๋”

const inlineCSS =
  process.env.NODE_ENV !== ENV_PRODUCTION && require('styles/index.scss');
...
      <Head>
        {inlineCSS && <style jsx global> {__html: inlineCSS} </style>}
          {process.env.NODE_ENV === ENV_PRODUCTION &&
            <link
              rel="stylesheet"
              type="text/css"
              href={`/static/styles/app.css?${this.props
                .__NEXT_DATA__.buildId}`}
            />}
      </Head>

๋„์›€์ด ๋˜์—ˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. ๋” ์ž์„ธํ•œ ์„ค๋ช…์ด ํ•„์š”ํ•œ ์‚ฌ๋žŒ์ด ์žˆ์œผ๋ฉด ์•Œ๋ ค์ฃผ์„ธ์š”. ๋” ๋งŽ์€ ์†”๋ฃจ์…˜์„ ๊ธฐ๋Œ€ํ•ฉ๋‹ˆ๋‹ค. ๋‹คํ–‰ํžˆ๋„ ๋ˆ„๊ตฐ๊ฐ€๋Š” ์—ฌ์ „ํžˆ ๋‹ค์†Œ ๊นŒ๋‹ค ๋กญ๊ณ  ์†์ด ๋งŽ์ด ๊ฑธ๋ฆฌ๋Š” ํ†ตํ•ฉ์ด๋ฏ€๋กœ ๊ฒฐ๊ตญ ์ข‹์€ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  .scss ํŒŒ์ผ์„ ๋‹จ์ผ CSS ํŒŒ์ผ๋กœ ์ถ”์ถœํ•˜๋Š” ๋Œ€์‹  ๊ฐ€์ ธ์˜จ ๊ฐ .scss ํŒŒ์ผ์„ ์ž์ฒด CSS ํŒŒ์ผ๋กœ ์ปดํŒŒ์ผํ•˜๋Š” ๊ฒƒ์ด ํ›จ์”ฌ ์ข‹์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒํ•˜๋ฉด ๊ฐ ํŽ˜์ด์ง€์—์„œ ํ•„์š”ํ•œ CSS ์Šคํƒ€์ผ ๋งŒ๋กœ๋“œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋ž˜๋„ ์–ด๋–ป๊ฒŒํ• ์ง€ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋‚ด ํ’€ ์š”์ฒญ์„ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค. ์ข‹์€ ํ•ด๊ฒฐ์ฑ…์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.
https://github.com/zeit/next.js/pull/2638

@ cr101 ์‚ฌ์‹ค์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ž์ฒด ๋‚ด๋ถ€ UI ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ๋กœ ๊ฐ€์ ธ์˜ค๊ณ  ์žˆ์œผ๋ฏ€๋กœ ํ•ญ์ƒ๋กœ๋“œ ํ•  ํŒŒ์ผ์˜ ํฐ ๋ฉ์–ด๋ฆฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค (์ด์ƒ์ ์ธ ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ ์—ฌ์ „ํžˆ ๊ทธ ์ง์Šน์„ ๋ชจ๋“ˆํ™”ํ•˜๋Š” ์ž‘์—…). compile and serve 1 file ์—์„œ X number of files at X locations ์ž…๋‹ˆ๋‹ค. ๋” ์ž‘์€ CSS ์ฒญํฌ์™€ ์™ธ๋ถ€ ์บ์‹ฑ ๊ฐ€๋Šฅํ•˜๊ณ  ์„ฑ๋Šฅ์ด ์ข‹์€ CDN ํ˜ธ์ŠคํŒ… ๋ฒ„์ „์œผ๋กœ ๋‚˜๋ˆ„๋Š” ์ ˆ์ถฉ์ ์„ ๊ณ ๋ คํ•  ๋•Œ ๋” ๋ณต์žกํ•ด ์ง€๋ฏ€๋กœ ์žฌ๋ฏธ ์žˆ์ง€๋งŒ ํ”„๋กœ์ ํŠธ ์ž์ฒด๋ฅผ ํฌํ•จํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ํŽธ์ง‘-Next๊ฐ€ ์ฒ˜๋ฆฌํ•˜๋ ค๋Š” ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚œ ๊ฒƒ์ด ํ™•์‹คํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ๋ชฉํ‘œ๋กœํ•ด์•ผํ•˜๋Š” ์ตœ์„ ์˜ ๋ฐฉ๋ฒ•์€ Next ํ”Œ๋Ÿฌ๊ทธ์ธ ๋˜๋Š” ํŒจํ„ด์ž…๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ์„ฑ๋Šฅ ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์ง€๋งŒ ์Šคํƒ€์ผ์ด ์ง€์ •๋œ ๊ตฌ์„ฑ ์š”์†Œ ๋˜๋Š” ์ด์™€ ์œ ์‚ฌํ•œ ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ๋งค์šฐ ๊ฐ„๋‹จํ•œ ์†”๋ฃจ์…˜์ž…๋‹ˆ๋‹ค. CSS ๋ž˜ํผ๋ฅผ ๋งŒ๋“œ์‹ญ์‹œ์˜ค.

import styled from 'styled-components';

const Collapse = props => (
  <__Collapse>
    { props.children }
  </__Collapse>
);

export default Collapse;

/**
 * CSS
 */
const __Collapse = styled.div`
  .rc-collapse {
    background-color: #f7f7f7;
    border-radius: 3px;
    border: 1px solid #d9d9d9;
  }
  ...
`;
import RcCollapse from 'rc-collapse';
import Collapse from '~/components/rc/Collapse';

const HelpPage = () => (
  <Collapse>
    <RcCollapse>
      <RcCollapse.Panel header="Title">Content</RcCollapse.Panel>
    </RcCollapse>
  </Collapse>
);

์ด ์ ‘๊ทผ ๋ฐฉ์‹์— ๋Œ€ํ•ด ๋‚ด๊ฐ€ ์ข‹์•„ํ•˜๋Š” ์ ์€ .css ๊ฐ€์ ธ์˜จ ๊ฒฝ์šฐ ์›๋ž˜ ๊ทœ์น™ ์œ„์— ์žฌ์ •์˜๋ฅผ ์ž‘์„ฑํ•˜์ง€ ์•Š๊ณ ๋„ ์†Œ์Šค CSS์—์„œ ์‚ฌ์šฉ์ž ์ •์˜ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค (์–ด์จŒ๋“  ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•จ). node_modules .css ํŒŒ์ผ.

๋‹ค์Œ์€ babel-plugin-inline-import๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ CSS ํŒŒ์ผ์„ ๊ฐ€์ ธ ์˜ค๋Š” ๊ฐ„๋‹จํ•œ ์†”๋ฃจ์…˜์ž…๋‹ˆ๋‹ค.

.babelrc

{
  "presets": ["next/babel"],
  "plugins": [
    [
      "inline-import",
      {
        "extensions": [".css"]
      }
    ]
  ]
}

ํŽ˜์ด์ง€ / ๊ตฌ์„ฑ ์š”์†Œ

import "prismjs";

import { PrismCode } from "react-prism";
import prismGlobalStyles from "prismjs/themes/prism.css";

export default () => {
    return (
        <div>
            <style global jsx>
                {prismGlobalStyles}
            </style>
            <PrismCode className="language-javascript">
                {`function(noop) {
                    return noop;
                }`}
            </PrismCode>
            {/* ... */}
        </div>
    );
};

@stovmascript ์ด๊ฒƒ์€ ์•„๋ฆ„๋‹ค์šด ์†”๋ฃจ์…˜์ด์ง€๋งŒ ์—ฌ์ „ํžˆ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค (https://github.com/Hacker0x01/react-datepicker์—์„œ .css ๋นŒ๋“œ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค). ์—ฌ๊ธฐ์„œ ๋‹ค๋ฅธ ๊ฒŒ์ž„์ด์—†๋Š” ๊ฒƒ์ด ํ™•์‹คํ•ฉ๋‹ˆ๊นŒ? ์˜ค๋ฅ˜๋กœ ์ธํ•ด ๋‹ค๋ฅธ ์ˆ˜์ค€์˜ CSS๋กœ๋“œ๊ฐ€ ํ•„์š”ํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

@hilarykitz , @stovmascript ์†”๋ฃจ์…˜์ด ์ €์—๊ฒŒ ํšจ๊ณผ์ ์ž…๋‹ˆ๋‹ค. ๋ฐœ์ƒํ•˜๋Š” ์˜ค๋ฅ˜๋ฅผ ๋ณด๋‚ด ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

@stovmascript- ๋ฐ”๋ฒจ ์บ์‹œ๋ฅผ ์–ด๋–ป๊ฒŒ ์ œ๊ฑฐํ•˜๊ณ 

  1. CSS ํŒŒ์ผ ๋งŒ๋“ค๊ธฐ
  2. ํŒŒ์ผ ๊ฐ€์ ธ ์˜ค๊ธฐ
  3. ๋Œ€๋‹ค
  4. CSS ํŒŒ์ผ ๋ณ€๊ฒฝ-์ƒˆ ์„ ํƒ๊ธฐ ๋ฐ ์Šคํƒ€์ผ ์ถ”๊ฐ€
  5. Babel Cache๊ฐ€ ์ด์ „ ๋ฒ„์ „์„ ์œ ์ง€ํ•˜๊ณ  ์žˆ์Œ์„ ๋ชฉ๊ฒฉํ•˜์‹ญ์‹œ์˜ค.

@ khrome83 ๋‹น์‹ ์€ node_modules / .cache๋ฅผ ์ง€์›Œ์•ผํ•ฉ๋‹ˆ๋‹ค

์บ์‹œ๋ฅผ ์ง€์šฐ๊ณ  ์œ„์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋Š” babel-inline-loader ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋” ๋‚˜์€ ์†”๋ฃจ์…˜์„ ์ฐพ์•˜์Šต๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์˜ ๋ฌธ์ œ๋Š” ์ „์—ญ ์Šคํƒ€์ผ ๋งŒ ์ ์šฉ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. <style jsx global> ํƒœ๊ทธ๊ฐ€ ์•„๋‹Œ ํƒœ๊ทธ์—์„œ ์‚ฌ์šฉํ•˜๋ฉด ๋ชฉ์ ์— ๋งž์ง€ ์•Š๊ฒŒ data-jsx๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ถ”๊ฐ€๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์บ์‹œ๋ฅผ ์ง€์šฐ๊ณ  ์œ„์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋Š” babel-inline-loader ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋” ๋‚˜์€ ์†”๋ฃจ์…˜์„ ์ฐพ์•˜์Šต๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์˜ ๋ฌธ์ œ๋Š” ์ „์—ญ ์Šคํƒ€์ผ ๋งŒ ์ ์šฉ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋น„์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ

@stovmascript ์˜ ์†”๋ฃจ์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์˜ˆ์ œ๋ฅผ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

https://github.com/zeit/next.js/pull/3157

๋‘˜ ์ด์ƒ์˜ ์™ธ๋ถ€ CSS๋ฅผ ์–ด๋–ป๊ฒŒ ํฌํ•จํ•ฉ๋‹ˆ๊นŒ?
๋™์ผํ•œ ๊ตฌ์„ฑ ์š”์†Œ์—์„œ ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ 2 ๊ฐœ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๊ฐ๊ฐ ๊ฐœ๋ณ„์ ์œผ๋กœ ์ž‘๋™ํ•˜์ง€๋งŒ ๊ฒฐํ•ฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

import rtStyle from 'react-table/react-table.css';
import dpStyle from 'react-datepicker/dist/react-datepicker.css';
...
render() {
    return (
      <div>
        {/* <style jsx global>{ rtStyle }</style> */}
        <style jsx global>{ dpStyle }</style>
...

@CHarnel ์‹œ๋„ <style jsx global>{ rtStyle }{dpStyle}</style>

@almeynman์ด ๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค :

Module build failed: SyntaxError: C:/.../components/activeUsersTable.js: 
Expected one child under JSX Style tag, but got 2 (eg: <style jsx>{`hi`}</style>)

@CHarnel์€ ๋‘˜ ๋‹ค ํ…œํ”Œ๋ฆฟ ๋ฌธ์ž์—ด์—

@CHarnel ์ด ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‹œ๋„ํ•˜์‹ญ์‹œ์˜ค.
<style jsx global>{ $ {rtStyle} $ {dpStyle} }</style>

๋ฟก๋ฟก

๋‚˜๋Š” ๊ทธ CSS๋ฅผ ํ•˜๋‚˜์˜ js ํŒŒ์ผ์— ๋„ฃ๊ณ  ๊ทธ๊ฒƒ์„ ๋‚ด๋ณด๋‚ด๋ ค๊ณ ํ•ฉ๋‹ˆ๋‹ค.

import bootstrap from 'bootstrap/dist/css/bootstrap.min.css'
import styles from './index.css'

export default bootstrap + styles

๊ทธ๋ฆฌ๊ณ  ๊ทธ๋ƒฅ

import styles from '../styles'
...
<style jsx global>{styles}</style>

https://github.com/sheerun/extracted-loader ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐœ๋ฐœ ๋ฐ ํ”„๋กœ๋•์…˜ ๋ชจ๋‘์— ExtractTextPlugin์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ฐœ๋ฐœ์‹œ ๋‹ค๋ฅธ html์„ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ CSS๋ฅผ js์— ์‚ฝ์ž… ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

@comus ๋‚˜๋Š” ๋‹น์‹ ์˜ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉ

@sheerun ์ข‹์€ ์‚ฌ๋žŒ, ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค

next.js์— ํ›จ์”ฌ ๋” ํฌ๊ด„์  ์ธ ์˜ˆ์ œ๋ฅผ ์ œ์ถœํ–ˆ์Šต๋‹ˆ๋‹ค.
https://github.com/zeit/next.js/pull/3451

์ด๊ฒƒ์€ nextjs v4 ์ด์ „์— ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค.

<style jsx global>{style}</style> <style jsx global>{colors}</style> <style jsx global>{layout}</style>

์ด aproach๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ jsx ์ „์—ญ ์Šคํƒ€์ผ์„๋กœ๋“œํ•˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? <style jsx global>{ rtStyle }{dpStyle}</style>

์ €๋Š” emit-files-loader ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ์†”๋ฃจ์…˜์„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ๊ด€์‹ฌ์ด ์žˆ๋‹ค๋ฉด ์—ฌ๊ธฐ์— ๊ฒŒ์‹œ ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์‚ฌ์šฉ์ž ์ •์˜ ์„œ๋ฒ„ ์„ค์ •์— ์˜์กดํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ .next ๋นŒ๋“œ ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด์—์„œ ๋‹จ์ผ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ •์ ์œผ๋กœ ์ œ๊ณต ํ•  ์ˆ˜ ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„์˜ /_next/... ๊ฒฝ๋กœ ๊ตฌ์กฐ์— ์˜์กดํ•˜์—ฌ ์„œ๋ฒ„์—†์ด ๊ตฌ์„ฑ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ ์™ธ์—๋Š” import stylesheet from './styles/style.[scss|less|stylus|w/e]'; ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์Šคํƒ€์ผ ์‹œํŠธ ํŒŒ์ผ์˜ ๊ณต์šฉ ๊ฒฝ๋กœ๊ฐ€๋˜๋ฏ€๋กœ <link> ๋„ฃ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜๊ตฌ ์บ์‹ฑ์„ ์œ„ํ•ด ?[hash] ๋˜๋ฉฐ ํ•ซ ๋ฆฌ๋กœ๋“œ๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

@nikolakanacki ๊ณต์‹ ์ง€์›์ด ๊ณง ๋„์ž… ๋  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค ๐Ÿ™ https://github.com/zeit/next.js/pull/3578

@timneutkens ๋‚˜๋Š” ์ด๊ฒƒ์„ ๋ณธ ์ ์ด ์žˆ๋Š”๋ฐ, "๋งค์šฐ ๊ณง"์— ๋Œ€ํ•œ ํ‰๊ฐ€๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ์ด๋ฏธ ์นด๋‚˜๋ฆฌ์•„์—์žˆ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
๋‚˜๋Š” ๋ฐ”๋กœ ํ•ด๊ฒฐ์ฑ…์ด ํ•„์š”ํ–ˆ๊ณ , ํ•˜๋‚˜๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด 2-3 ์ผ์„ ๋ณด๋ƒˆ๊ณ , ๊ธฐ๋ณธ์ ์œผ๋กœ "์‰ฌ์šด ์ˆ˜์ •"์ธ ๋‚˜๋งŒ์˜ ์†”๋ฃจ์…˜์„ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ extract-text-webpack-plugin ๊ฒฐํ•ฉํ•˜์—ฌ ๋ชจ๋“  ๋ณ„๋„์˜ .[css|stylus|less|scss] ํŒŒ์ผ์„ ์ •์ ์œผ๋กœ ์กฐ์ธํ•˜๊ณ  ๋‹ค์Œ ์—†์ด๋„ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋‹จ์ผ ์ •์  ๋ฆฌ์†Œ์Šค๋กœ ๋ชจ๋‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋กํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๊ณ ๋ คํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ์˜์ด๋ฉด์—์žˆ๋Š” ์ฃผ์š” ๋ฌธ์ œ๋Š” ํ”„๋กœ๋•์…˜ ๋ฐ ๊ฐœ๋ฐœ ๋นŒ๋“œ ๋’ค์— ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ๋งŽ์€ "๋งˆ๋ฒ•"์ด ์ง„ํ–‰๋˜๊ณ  ์žˆ์œผ๋ฉฐ ํ•ซ ๋ฆฌ๋กœ๋”ฉ ๋ฐ ๊ธฐํƒ€ ์ž‘์—…์ด ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์†Œ์Šค๋ฅผ ์ฝ๊ณ  ์–ด๋–ป๊ฒŒ ์กฐ๋ฆฝ๋˜๋Š”์ง€ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ๊ฒƒ์„ ๋งŒ๋“  ์‚ฌ๋žŒ์ด ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ๋ฌธ์„œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ๋” ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ๊ธฐ์—ฌํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

@kimsj_ssj แ„ แ„ แ„ แ„ แ„ แ„

์ด ํŒŒ์ผ์„ extract-text-webpack-plugin๊ณผ ๊ฒฐํ•ฉํ•˜์—ฌ ๋ณ„๋„์˜ ๋ชจ๋“ . [css | stylus | less | scss] ํŒŒ์ผ์„ ์ •์ ์œผ๋กœ ์กฐ์ธํ•˜๊ณ  ๋‹ค์Œ์—†์ด ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋‹จ์ผ ์ •์  ๋ฆฌ์†Œ์Šค๋กœ ๋ชจ๋‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋กํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์ƒ๊ฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. .

๋‹ค์Œ v5 ์šฉ์œผ๋กœ ์ž‘์„ฑํ•œ ํ”Œ๋Ÿฌ๊ทธ์ธ์€ ์ด๋ฏธ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ๊ณง ์˜คํ”ˆ ์†Œ์Šค๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค ๐Ÿ‘

๋‚ด๋ถ€ ๋ฌธ์„œ ์ž‘์„ฑ๊ณผ ๊ด€๋ จํ•˜์—ฌ v5๊ฐ€ ์ถœ์‹œ ๋œ ํ›„ ๋ชจ๋“  ๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ๋ฌธ์„œํ™” ํ•  ๊ณ„ํš์ž…๋‹ˆ๋‹ค.

@timneutkens ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

@timneutkens ์—…๋ฐ์ดํŠธ์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.์ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์—ฌ๊ธฐ์— ์—…๋ฐ์ดํŠธ๋ฅผ ๊ฒŒ์‹œํ•˜์‹ญ์‹œ์˜ค!

์ด๊ฒƒ์— ๋Œ€ํ•œ ์†Œ์‹์ด ์žˆ์Šต๋‹ˆ๊นŒ?

๋‹ค๋ฅธ ์†Œ์‹์ด ๋ฌด์—‡์ธ์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค ๐Ÿค”

์ด๊ฒƒ์€ Next.js v5์—์„œ ๋ฆด๋ฆฌ์Šค๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
Readme https://github.com/zeit/next.js#importing -css--sass--less--stylus-files์—๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ์–ธ๊ธ‰ ๋œ PR์ด ํ•ฉ๋ณ‘๋˜์–ด์ด ๋ฌธ์ œ๊ฐ€ ์ข…๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋ฃจํŠธ ํ”„๋กœ์ ํŠธ์— / static ํด๋”๋ฅผ ๋งŒ๋“ค๊ณ  / static ์•ˆ์— file.css๋ฅผ ๋„ฃ์€ ๋‹ค์Œ ํ—ค๋” html ๊ตฌ์กฐ ํ˜ธํฌ์—.

import Head from 'next/head';
<Head>
          <meta charset="utf-8" />
          <link rel="stylesheet" href="/static/css/custom.css" />
</Head>

๊ทธ๋Ÿฐ ๋‹ค์Œ ์–ด๋””์„œ๋‚˜ className์„ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค!

@comus

๋งค์šฐ ํฌ๊ด„์ ์ด๊ณ  ๋˜‘๋˜‘ํ•ฉ๋‹ˆ๋‹ค .. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค .. ํ•˜๋ฃจ ์ข…์ผ ์ด๋Ÿฐ ์ข…๋ฅ˜์˜ ์†”๋ฃจ์…˜์„ ์ฐพ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค ..

๋ฃจํŠธ ํ”„๋กœ์ ํŠธ์— / static ํด๋”๋ฅผ ๋งŒ๋“ค๊ณ  file.css๋ฅผ / static ์•ˆ์— ๋„ฃ์€ ๋‹ค์Œ Header html structure hock์— ๋„ฃ์œผ์‹ญ์‹œ์˜ค.

import Head from 'next/head';
<Head>
          <meta charset="utf-8" />
          <link rel="stylesheet" href="/static/css/custom.css" />
</Head>

๊ทธ๋Ÿฐ ๋‹ค์Œ ์–ด๋””์„œ๋‚˜ className์„ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค!

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ฃจํŠธ (package.json ํŒŒ์ผ์ด์žˆ๋Š” ์œ„์น˜)์— '๊ณต์šฉ'ํด๋”๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

# 8626์„ ํ†ตํ•ด ์ง€์›์ด ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค!

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰