Rails, Webpacker: pug and sass loaders

Rails, Webpacker: pug and sass loaders

Кто работает c  Pug, Slim, Sass никогда больше не возвратятся к "чистому" HTML,CSS коду по крайней мере по своей воле. Скорость кодирования высока, ошибок меньше.

Rails 6.0.x, Webpacker 5.x (5.2)

(2020-10)

Не получается запустить "из коробки" связку Sass, Vue, Pug. Прошло уже много времени, но различные варианты работы остаются и общего решения нет. Rails это отличный backend для приложений, Vue отличный frontend framework (javascript).

Сам webpacker это обертка над webpack для использования в экосистеме Rails. Сейчас это официальные рекомендованный способ работы над клиентской частью приложения, функциональность в браузере.

Предположим, что после стандартной установки все работает  как надо.

rails webpacker:install
rails webpacker:install:vue

Чтобы связка sass/pug/vue заработала

  • изменить параметры загрузчика sass-loader
  • установить доп. пакеты
  • добавить теги подключения во views

Доп. пакеты

yarn add --dev pug pug-plain-loader sass fibers resolve-url-loader

Мы говорим о связке sass (dart-sass) и fibers. Это современно и  быстро.

Настройка pug

// config/webpacker/loaders/pug.js
module.exports = {
  test: /\.pug$/,
  use: [{
    loader: 'pug-plain-loader'
  }]
}

Настройки sass-loader

// config/webpacker/environment.js
const { environment } = require('@rails/webpacker')
const { VueLoaderPlugin } = require('vue-loader')

// vue loader создается при установке
const vue = require('./loaders/vue')
// pug добавляем
const pug = require('./loaders/pug')

environment.plugins.prepend('VueLoaderPlugin', new VueLoaderPlugin())
environment.loaders.prepend('pug', pug)
environment.loaders.prepend('vue', vue)

// sass-loader configs
const sassLoader = environment.loaders.get('sass').use.find(item => item.loader === 'sass-loader')

// use dart sass
sassLoader.options.implementation = require('sass')
// use fibers
sassLoader.options.sassOptions.fiber = require('fibers')
// syntax
sassLoader.options.sassOptions.indentedSyntax = true
// urls
environment.loaders.get('sass').use.splice(-1, 0, {
  loader: 'resolve-url-loader'
});

/**
 * доступные опции dart sass
 * @see https://github.com/sass/dart-sass#javascript-api
 */
sassLoader.options.sourceMap = true

module.exports = environment

во vue компоненте укажем соответствующие настройки

<template lang="pug">
  #app
    p {{ message }}
</template>

<script>
export default {
  data: function () {
    return {
      message: "Hello Vue!"
    }
  }
}
</script>

<style lang="sass" scoped>
  #app
    background: blue!important
    color: #fff  
</style>
app/javascript/app.vue
import Vue from 'vue'
import App from '../app.vue'

document.addEventListener('DOMContentLoaded', () => {

  const app = new Vue({
    render: h => h(App)
  }).$mount()

  document.body.appendChild(app.$el)
})
app/javascript/packs/hello_vue.js

подключение в шаблоне

= stylesheet_pack_tag 'hello_vue'
= javascript_pack_tag 'hello_vue'

запускаем и проверяем работу

# compile
./bin/webpack
# or server
./bin/webpack-dev-server

Вариант настройки Rails 5.2, Webpacker 3.x (устарело)

Установим все необходимые модули

yarn add --dev pug pug-plain-loader sass-loader node-sass vue-style-loader css-loader

файлы в директории config/webpack/loaders

  • pug.js
  • sass.js

sass.js

/**
 * @see https://vue-loader.vuejs.org/ru/guide/pre-processors.html#sass
 */
module.exports = {
  test: /\.sass$/,
  use: [
    'vue-style-loader',
    'css-loader',
    {
      loader: 'sass-loader',
      options: {
        indentedSyntax: true,

        /**
         * передача глобальных переменных
         *
         * sass-loader также поддерживает опцию data, которая позволяет
         * вам передавать общие переменные во все обрабатываемые файлы
         * без необходимости везде их явно импортировать
         *
         * можно указать файл, например `variables.scss`
         */
        // data: `$color: red;`
      }
    }
  ]
}

pug.js

/**
 * Вместо использования pug-loader мы должны использовать загрузчик,
 * который вернёт сырую строку HTML, например pug-plain-loader
 *
 * @see https://vue-loader.vuejs.org/ru/guide/pre-processors.html#pug
 */
module.exports = {
  test: /\.pug$/,
  loader: 'pug-plain-loader'
}

/**
 * Если вы также собираетесь импортировать файлы .pug как HTML-строки
 * в JavaScript, вам нужно добавить в цепочку raw-loader после загрузчика
 * пре-процессора. Обратите внимание, что добавление raw-loader сломает
 * использование в компонентах Vue, поэтому потребуется два правила: одно
 * для файлов Vue с использованием resourceQuery, другое (fallback) для
 * импортов из JavaScript
 */
// module.exports = {
//   test: /\.pug$/,
//   oneOf: [
//     // это применяется к `<template lang="pug">` в компонентах Vue
//     {
//       resourceQuery: /^\?vue/,
//       use: ['pug-plain-loader']
//     },
//     // это применяется к импортам pug внутри JavaScript
//     {
//       use: ['raw-loader', 'pug-plain-loader']
//     }
//   ]
// }

И добавляем  в файл конфигурации config/webpack/environment.js

const { environment } = require('@rails/webpacker')
const { VueLoaderPlugin } = require('vue-loader')
const vue = require('./loaders/vue')

// *** 1
const pug = require('./loaders/pug')
const sass = require('./loaders/sass')
// --

environment.plugins.prepend('VueLoaderPlugin', new VueLoaderPlugin())

// *** 2
environment.loaders.prepend('sass', sass)
environment.loaders.prepend('pug', pug)
// -

environment.loaders.prepend('vue', vue)
module.exports = environment