質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.92%

[Rails][Sass] @importを使った場合、SourceMapが正しく解釈されない

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 205

stimlocy

score 9

環境

Rails 6.0.3.2
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-darwin18]

### Gemfile
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.6.5'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 6.0.3', '>= 6.0.3.2'
# Use sqlite3 as the database for Active Record
gem 'sqlite3', '~> 1.4'
# Use Puma as the app server
gem 'puma', '~> 4.1'
# Use SCSS for stylesheets
gem 'sass-rails', '>= 6'
# Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker
gem 'webpacker', '~> 4.0'
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
# gem 'turbolinks', '~> 5'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.7'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 4.0'
# Use Active Model has_secure_password
# gem 'bcrypt', '~> 3.1.7'

# Use Active Storage variant
# gem 'image_processing', '~> 1.2'

# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', '>= 1.4.2', require: false

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
end

group :development do
  # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
  gem 'web-console', '>= 3.3.0'
  gem 'listen', '~> 3.2'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
end

group :test do
  # Adds support for Capybara system testing and selenium driver
  gem 'capybara', '>= 2.15'
  gem 'selenium-webdriver'
  # Easy installation and use of web drivers to run system tests with browsers
  gem 'webdrivers'
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
### package.json
{
  "name": "sass_test",
  "private": true,
  "dependencies": {
    "@rails/actioncable": "^6.0.0",
    "@rails/activestorage": "^6.0.0",
    "@rails/ujs": "^6.0.0",
    "@rails/webpacker": "4.2.2"
  },
  "version": "0.1.0",
  "devDependencies": {
    "webpack-dev-server": "^3.11.0"
  }
}

問題のファイル構成について

問題のcssファイルは以下の構成です

app
 |-- assets
   |-- stylesheets
     |-- application.css
     |-- common.scss
     |-- reset.scss
     |-- scaffold.scss
     |-- partial
       |-- _value.scss


application.css

/*
 *= require reset.css
 *= require scaffolds.css
 *= require common.css
 *= require_directory .
 *= require_self
 */


common.scss

@import "./partial/values";

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  font-family: sans-serif;
  font-size: 16px;
  text-align: justify;
}

h1, h2, h3, h4, h5, h6 {
  color: red;
}


_value.scss

@for $i from 1 through 50 { // 1, 2, 3 ... 50
  .w-#{$i}em { width:  #{$i}em !important; }
  .h-#{$i}em { height: #{$i}em !important; }
}

発生している内容

chromeのデベロッパーツールで、scssの行を確認しようとすると、実際の行とは違う位置を示しています。
develop-tool
イメージ説明

_value.scssで実際にCSSとして書き出されるのは399行です。
common.scssでh1, h2, h3 ...が記述されているのは14~16行ですから、_value.scssがcommon.scss内に展開されたような行数で反映されてしまっています。

@importを利用せず、application.cssで以下のように記述すると、正しい行数を示すようになります。

/*
 *= require reset.css
 *= require scaffolds.css
 *= require partial/_values.css
 *= require common.css
 *= require_directory .
 *= require_self
 */

また、デベロッパーツールでSourcesの「Enable CSS source maps」を外し、SourceMapを解釈しないようにすれば、正しい行位置を示すようになります。
イメージ説明
イメージ説明
イメージ説明

期待する解決

scssファイル内で@importを利用した上で、chromeのデベロッパーツールがSouceMapを正しい解釈をして行位置を示すようにしたいのです。

全てapplication.cssで記述すれば正しくは動くのですが、その場合はsassのPartialを利用した管理方法や、特定のセレクタにネストさせるような展開方法が利用できません。

これを解決する方法はありますか?
また、この問題はscssをコンパイルしているgemの問題か、sourcemapを解釈しようとするchromeの問題でしょうか?

試行錯誤

gem "sass-rails"を除き、gem "sassc-rails"に追加して
https://github.com/sass/sassc-rails#inline-source-maps
を実施しましたが、特に変化はありませんでした。

https://github.com/rails/sprockets/issues/656
上記URLは、sass-railsが依存している?sprocketsのもので、今回の問題とは微妙に違いますが、なにか関係があるかもしれません。
@importの場合で上手く読むことが出来ない、という点では共通しているかと思われます。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

Railsには、Ssasの @import によるファイルのインポートとは別で、アセットパイプラインというCSSやJSなどのアセットを結合する機能(sprockets-rails)が備わっています。

application.css

/*
 *= require reset.css
 *= require scaffolds.css
 *= require common.css
 *= require_directory .
 *= require_self
 */


この指定がアセットパイプラインを使用してファイルを結合するマニフェストになっていて、これがSass/SCSSの@importと二重に動作している状況が現在の問題を引き起こしているように思います。

本来は、アセットパイプラインはSass/SCSSの @import と混在させて運用するべきではありません。
Railsガイドでも以下のように注意をしています

Sassファイルを複数使用しているのであれば、Sprocketsディレクティブで読み込まずにSass @importルールを使用する必要があります。このような場合にSprocketsディレクティブを使用してしまうと、Sassファイルが自分自身のスコープに置かれるため、その中で定義されている変数やミックスインが他のSassから利用できなくなってしまいます。
アセットパイプライン - Railsガイド

Sass/SCSSらしく @import を使ってパーシャルに書いた変数やmixinを別ファイルで展開する運用をしたいのでしたら、Sprocketsが結合してしまわないように除外した方がいいと思います。

以下参考にしてみてください

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/08/04 14:16

    ありがとうございます。
    SprocketsからWebpackerに移行し、sass-loaderでsourceMapオプションを追加することで、解決できました。

    Webpackerに移行しただけでは、CSSのsourceMapが有効にならず
    sass-loaderを設定するのにだいぶ手間取りました。

    # scssファイル移動
    app/assets/stylesheets → app/javascript/stylesheets

    ```javascript
    // app/javascript/packs/application.js
    import '../javascripts/application';
    import '../stylesheets/application';
    ```

    ```html.erb
    <!-- app/views/layouts/application.html.erb -->

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


    # Webpackの設定

    package.json
    ```json
    {
    "name": "sass_test",
    "private": true,
    "dependencies": {
    "@rails/actioncable": "^6.0.0",
    "@rails/activestorage": "^6.0.0",
    "@rails/ujs": "^6.0.0",
    "@rails/webpacker": "4.2.2",
    "source-map": "^0.7.3",
    "webpack-sources": "^1.4.3"
    },
    "version": "0.1.0",
    "devDependencies": {
    "fibers": "^5.0.0",
    "sass": "^1.26.10",
    "sass-loader": "^7.2.0",
    "webpack": "^4.44.1",
    "webpack-dev-server": "^3.11.0",
    "webpack-merge": "^5.1.0"
    }
    }
    ```

    ```javascript
    // app/config/webpack/environment.js

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

    const { merge } = require('webpack-merge');
    const SassLoader = environment.loaders.get('sass').use.find(el => el.loader === 'sass-loader')
    SassLoader.options = merge(SassLoader.options, {
    sourceMap: true,
    implementation: require('sass'),
    fiber: require('fibers')
    })

    module.exports = environment
    ```

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.92%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る