Rails 6.1, TailwindCSS JIT, Webpacker 및 PostCSS 8 시작하기

51616 단어
이것은 내 첫 번째 게시물이며 Webpacker를 통해 PostCSS 8.0을 사용하여 Rails 6.1 앱에서 멋진 JIT(적시) 컴파일 설정으로 TailwindCSS를 가져오는 방법을 살펴보겠습니다.

새 Rails 앱 만들기




rails new tails_on_rails


Gemfile 업데이트 웹패커에서

# Replace
gem 'webpacker', '~> 5.0'

# With
gem 'webpacker', '~> 5.4.0'


번들러 실행

bundle


기본 웹패커 제거

yarn remove @rails/webpacker


필요한 버전의 Webpacker 및 기타 종속성을 추가합니다.

yarn add @rails/[email protected] @fullhuman/postcss-purgecss@^4.0.3 postcss@^8.2.10 postcss-loader@^4.0.3 sass@^1.32.7 autoprefixer@^10.2.6

package.json는 다음과 같아야 합니다.

{
  "name": "tails-on-rails",
  "private": true,
  "dependencies": {
     "@fullhuman/postcss-purgecss": "^4.0.3",
     "@rails/actioncable": "^6.0.0",
     "@rails/activestorage": "^6.0.0",
     "@rails/ujs": "^6.0.0",
     "@rails/webpacker": "5.4.0",
     "postcss": "^8.2.10",
     "postcss-loader": "^4.0.3",
     "sass": "^1.32.7",
     "turbolinks": "^5.2.0",
     "webpack": "^4.46.0",
     "webpack-cli": "^3.3.12"
    },
  "version": "0.1.0",
  "devDependencies": {
    "webpack-dev-server": "^3.11.2"
 }
}


TailwindsCSS 및 공식 플러그인을 설치합니다.

yarn add tailwindcss @tailwindcss/forms @tailwindcss/typography @tailwindcss/aspect-ratio @tailwindcss/typography @tailwindcss/line-clamp

package.json는 다음과 같아야 합니다.

{
  "name": "tails-on-rails",
  "private": true,
  "dependencies": {
    "@fullhuman/postcss-purgecss": "^4.0.3",
    "@rails/actioncable": "^6.0.0",
    "@rails/activestorage": "^6.0.0",
    "@rails/ujs": "^6.0.0",
    "@rails/webpacker": "5.4.0",
    "@tailwindcss/aspect-ratio": "^0.2.1",
    "@tailwindcss/forms": "^0.3.3",
    "@tailwindcss/typography": "^0.4.1",
    "postcss": "^8.2.10",
    "postcss-loader": "^4.0.3",
    "sass": "^1.32.7",
    "tailwindcss": "^2.1.4",
    "turbolinks": "^5.2.0",
    "webpack": "^4.46.0",
    "webpack-cli": "^3.3.12"
  },
  "version": "0.1.0",
  "devDependencies": {
    "webpack-dev-server": "^3.11.2"
  }
}


사용자 지정 CSS 파일을 만듭니다.

mkdir app/javascript/stylesheets && touch app/javascript/stylesheets/application.scss


app/javascript/stylesheets/application.scss에 다음을 추가합니다.

@import "tailwindcss/base";

@import "tailwindcss/components";

@import "tailwindcss/utilities";


여기에 있는 동안 사용자 지정 구성 요소를 추가하여 @apply 지시문이 작동하는지 확인합니다.
app/javascript/stylesheets/application.scss에 다음을 추가합니다.

.btn {
  @apply px-4 py-2 bg-blue-600 text-white rounded; 
}

application.scss는 다음과 같아야 합니다.

@import "tailwindcss/base";

@import "tailwindcss/components";

.btn {
  @apply px-4 py-2 bg-blue-600 text-white rounded; 
}

@import "tailwindcss/utilities";

app/javascript/packs/application.js에 다음을 추가합니다.

import "stylesheets/application.scss"

application.js는 다음과 같아야 합니다.

import Rails from "@rails/ujs"
import Turbolinks from "turbolinks"
import * as ActiveStorage from "@rails/activestorage"
import "channels"
import "stylesheets/application.scss"

Rails.start()
Turbolinks.start()
ActiveStorage.start()


앱 루트 파일postcss.config.js에서 TailwindCSS가 필요합니다.

require('tailwindcss'),

postcss.config.js는 다음과 같아야 합니다.

module.exports = {
  plugins: [
    require('tailwindcss'),
    require('postcss-import'),
    require('postcss-flexbugs-fixes'),
    require('postcss-preset-env')({
      autoprefixer: {
        flexbox: 'no-2009'
      },
      stage: 3
    })
  ]
}

app/views/layouts/application.html.erb에 다음을 추가하십시오.

<link rel="stylesheet" href="https://rsms.me/inter/inter.css">

<%= stylesheet_pack_tag 'application', 'data-turbolinks-track': 'reload' %>

application.html.erb는 다음과 같아야 합니다.

<!DOCTYPE html>
<html>
  <head>
    <title>TailsOnRails</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <link rel="stylesheet" href="https://rsms.me/inter/inter.css">

    <%= stylesheet_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <%= yield %>
  </body>
</html>


전체 TailwindCSS 스캐폴드tailwind.config.js
npx tailwindcss init --full


위의 내용은 구성 가능한 큰 TailwindCSS 파일을 생성합니다.

TailwindCSS 플러그인을 tailwind.config.js에 추가합니다(plugins: [] 노드의 파일 맨 아래 오른쪽).

plugins: [
  require('@tailwindcss/typography'),
  require('@tailwindcss/forms'),
  require('@tailwindcss/line-clamp'),
  require('@tailwindcss/aspect-ratio'),
]

Inter 글꼴을 fontFamilytailwind.config.js 노드에 추가합니다.

fontFamily: {
  sans: [
    'Inter var',
       ...


JIT 활성화 - tailwind.config.js 파일 상단의 적시 컴파일

module.exports = {
  mode: 'jit',
  purge: [],

tailwind.config.js 파일에서 제거 옵션 구성

purge: {
enabled: ["production", "staging"].includes(process.env.NODE_ENV),
content: [
  './app/views/**/*.html.erb',
  './app/helpers/**/*.rb',
  './app/javascript/**/*.js',
],
},


tailwind.config.js는 다음과 같아야 합니다.

const colors = require('tailwindcss/colors')

module.exports = {
  mode: 'jit',
  purge: {
    enabled: ["production", "staging"].includes(process.env.NODE_ENV),
    content: [
      './**/*.html.erb',
      './app/helpers/**/*.rb',
      './app/javascript/**/*.js',
    ],
  },
  presets: [],
  darkMode: false, // or 'media' or 'class'
  theme: {
    screens: {
      sm: '640px',
      md: '768px',
      lg: '1024px',
      xl: '1280px',
      '2xl': '1536px',
    },
    colors: {
      transparent: 'transparent',
      current: 'currentColor',

      // content removed ....

    flexGrow: {
      0: '0',
      DEFAULT: '1',
    },
    flexShrink: {
      0: '0',
      DEFAULT: '1',
    },
    fontFamily: {
      sans: [
        'Inter var',
        'ui-sans-serif',
        'system-ui',
        '-apple-system',
        'BlinkMacSystemFont',
        '"Segoe UI"',
        'Roboto',
        '"Helvetica Neue"',
        'Arial',
        '"Noto Sans"',
        'sans-serif',
        '"Apple Color Emoji"',
        '"Segoe UI Emoji"',
        '"Segoe UI Symbol"',
        '"Noto Color Emoji"',
      ],
      serif: ['ui-serif', 'Georgia', 'Cambria', '"Times New Roman"', 'Times', 'serif'],
      mono: [
        'ui-monospace',
        'SFMono-Regular',
        'Menlo',

      // content removed ....

    zIndex: ['responsive', 'focus-within', 'focus'],
  },
  plugins: [
    require('@tailwindcss/typography'),
    require('@tailwindcss/forms'),
    require('@tailwindcss/line-clamp'),
    require('@tailwindcss/aspect-ratio'),],
}

babel.config.js 파일에서 다음을 설정합니다.

...
'@babel/plugin-transform-runtime',
{
  helpers: false,
  regenerator: true,
  corejs: false
}

babel.config.js에 다음을 추가합니다.

['@babel/plugin-proposal-private-methods', { loose: true }]

babel.config.js는 다음과 같아야 합니다.

module.exports = function (api) {
  var validEnv = ['development', 'test', 'production']
  var currentEnv = api.env()
  var isDevelopmentEnv = api.env('development')
  var isProductionEnv = api.env('production')
  var isTestEnv = api.env('test')

  if (!validEnv.includes(currentEnv)) {
    throw new Error(
      'Please specify a valid `NODE_ENV` or ' +
        '`BABEL_ENV` environment variables. Valid values are "development", ' +
        '"test", and "production". Instead, received: ' +
        JSON.stringify(currentEnv) +
        '.'
    )
  }

  return {
    presets: [
      isTestEnv && [
        '@babel/preset-env',
        {
          targets: {
            node: 'current'
          }
        }
      ],
      (isProductionEnv || isDevelopmentEnv) && [
        '@babel/preset-env',
        {
          forceAllTransforms: true,
          useBuiltIns: 'entry',
          corejs: 3,
          modules: false,
          exclude: ['transform-typeof-symbol']
        }
      ]
    ].filter(Boolean),
    plugins: [
      'babel-plugin-macros',
      '@babel/plugin-syntax-dynamic-import',
      isTestEnv && 'babel-plugin-dynamic-import-node',
      '@babel/plugin-transform-destructuring',
      [
        '@babel/plugin-proposal-class-properties',
        {
          loose: true
        }
      ],
      [
        '@babel/plugin-proposal-object-rest-spread',
        {
          useBuiltIns: true
        }
      ],
      [
        '@babel/plugin-transform-runtime',
        {
          helpers: false,
          regenerator: true,
          corejs: false
        }
      ],
      [
        '@babel/plugin-transform-regenerator',
        {
          async: false
        }
      ],
      ['@babel/plugin-proposal-private-methods', { loose: true }]
    ].filter(Boolean)
  }
}


Webpacker가 이 버전의 Postcss와 함께 작동하려면 로더를 사용하도록 지시해야 합니다.config/webpack/environment.js에 다음을 추가합니다. 기존 두 줄 사이에 삽입하십시오.

// Get the actual sass-loader config
const sassLoader = environment.loaders.get('sass')
const sassLoaderConfig = sassLoader.use.find(function (element) {
return element.loader == 'sass-loader'
})

// Use Dart-implementation of Sass (default is node-sass)
const options = sassLoaderConfig.options
options.implementation = require('sass')

function hotfixPostcssLoaderConfig (subloader) {
  const subloaderName = subloader.loader
  if (subloaderName === 'postcss-loader') {
    subloader.options.postcssOptions = subloader.options.config
    delete subloader.options.config
  }
}

environment.loaders.keys().forEach(loaderName => {
  const loader = environment.loaders.get(loaderName)
  loader.use.forEach(hotfixPostcssLoaderConfig)
})

environment.js는 다음과 같아야 합니다.

const {environment} = require('@rails/webpacker')

// Get the actual sass-loader config
const sassLoader = environment.loaders.get('sass')
const sassLoaderConfig = sassLoader.use.find(function (element) {
return element.loader == 'sass-loader'
})

// Use Dart-implementation of Sass (default is node-sass)
const options = sassLoaderConfig.options
options.implementation = require('sass')

function hotfixPostcssLoaderConfig(subloader) {
  const subloaderName = subloader.loader
  if (subloaderName === 'postcss-loader') {
    subloader.options.postcssOptions = subloader.options.config
    delete subloader.options.config
  }
}

environment.loaders.keys().forEach(loaderName => {
const loader = environment.loaders.get(loaderName)
loader.use.forEach(hotfixPostcssLoaderConfig)
})

module.exports = environment


이 설정을 테스트해 보겠습니다.

rails g controller Home index 

app/views/home/index.html.erb에 다음을 추가합니다.

<div class="font-sans bg-white h-screen flex flex-col w-full">
  <div class="h-screen bg-gradient-to-r from-green-400 to-blue-500">
    <div class="px-4 py-48">
     <div class="relative w-full text-center">
       <h1 class="animate-pulse font-bold text-gray-200 text-2xl mb-6">
        Your TailwindCSS setup is working if this pulses...
       </h1>
    </div>
   </div>
  </div>
</div>

/home/index에서 위의 config/routes.rb를 가리키는 루트 경로를 추가합니다.

root 'home#index'


하나의 터미널에서 실행bin/webpack-dev-server그리고 또 다른 실행에서rails s

⚠️ Do not try running webpack-dev-server without the bin/ prefix as it's likely it will fail to compile.



당신은 이것을보아야합니다


@apply 지시문을 테스트하려면 app/views/home/index.html.erb에서 다음을 class="pulsing-text"로 바꿉니다.

class="animate-pulse font-bold text-gray-200 text-2xl mb-6"

app/javascript/stylesheets/application.scss에 다음을 추가합니다.

.pulsing-text {
@apply animate-pulse font-bold text-gray-200 text-2xl mb-6;
}

applications.scss는 다음과 같아야 합니다.

@import "tailwindcss/base";

@import "tailwindcss/components";

.pulsing-text {
@apply animate-pulse font-bold text-gray-200 text-2xl mb-6;
}

@import "tailwindcss/utilities";


브라우저에서 홈 페이지를 새로 고칠 때 이 메시지가 계속 표시되어야 합니다.



GitHub Repo

좋은 웹페이지 즐겨찾기