rails/webpacker

css-loader error Unclosed string in sass files with quotes

julian-fullcrum opened this issue · 2 comments

Problem Statement

css-loader as part of the default webpacker configuration is not able to interpret quotes in scss files, for example If any of my scss files contains a single (') or double (") quote, webpack throws an Unclosed string Error.

If I try to import a .scss file with this instruction

&:after {
  content: ']';
 }

or declarate a new font-family variable (with quotes):

$font-family-lato: 'Lato', sans-serif;

webpacker:compile throws an CssSyntaxError: Unclosed string

CssSyntaxError

(30:8) /app/frontend/stylesheets/styles.scss Unclosed string

  28 |       }
  29 |       &:after {
> 30 |         content: ']';
     |        ^
  31 |       }
  32 |     }
 @ ./stylesheets/application.scss
 @ ./packs/admin/application.js 5:135-178

Configuration

This is my base.js configuration:

const path = require("path");
const { webpackConfig, merge } = require("@rails/webpacker");
const WebpackAssetsManifest = require("webpack-assets-manifest");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

const manifestPlugin = webpackConfig.plugins.find(
  (r) => r instanceof WebpackAssetsManifest
);
if (manifestPlugin) {
  manifestPlugin.options.contextRelativeKeys = true;
}

const customConfig = {
  context: path.resolve(__dirname, "../../app/frontend"),
  resolve: {
    alias: {
      "@vendor-js": path.resolve(__dirname, "../../vendor/assets/javascripts"),
      "@vendor-css": path.resolve(__dirname, "../../vendor/assets/stylesheets"),
      "@vendor-img": path.resolve(__dirname, "../../vendor/assets/images"),
      "@front-js": path.resolve(__dirname, "../../app/frontend/javascripts"),
      "@front-css": path.resolve(__dirname, "../../app/frontend/stylesheets"),
      "@front-img": path.resolve(__dirname, "../../app/frontend/images"),
      "@lib": path.resolve(__dirname, "../../lib/assets"),
    },
    extensions: [".css"],
  },
  module: {
    strictExportPresence: true,
    rules: [
      {
        test: [/\.html$/],
        exclude: [/\.(js|mjs|jsx|ts|tsx)$/],
        type: "asset/source",
      },
      {
        test: [
          /\.bmp$/,
          /\.gif$/,
          /\.jpe?g$/,
          /\.png$/,
          /\.tiff$/,
          /\.ico$/,
          /\.avif$/,
          /\.webp$/,
          /\.eot$/,
          /\.otf$/,
          /\.ttf$/,
          /\.woff$/,
          /\.woff2$/,
          /\.svg$/,
        ],
        exclude: [/\.(js|mjs|jsx|ts|tsx)$/],
        type: "asset/resource",
        generator: { filename: "static/[hash][ext][query]" },
      },
      {
        test: /\.(css)$/i,
        use: [
          "mini-css-extract-plugin",
          {
            loader: "css-loader",
            options: { sourceMap: true, importLoaders: 2 },
          },
          {
            loader: "postcss-loader",
            options: { sourceMap: true },
          },
        ],
      },
      {
        test: /\.(scss|sass)(\.erb)?$/i,
        use: [
          "mini-css-extract-plugin",
          {
            loader: "css-loader",
            options: { sourceMap: true, importLoaders: 2 },
          },
          {
            loader: "resolve-url-loader",
            options: { sourceMap: true, removeCR: true, attempts: 1 },
          },
          {
            loader: "sass-loader",
            options: {
              sassOptions: { includePaths: ["vendor/assets"] },
              implementation: require("sass"),
            },
          },
        ],
      },
      {
        test: /\.(js|jsx|mjs|ts|tsx|coffee)?(\.erb)?$/,
        include: [
          // "../../app/frontend",
          // "../../vendor/assets",
        ],
        exclude: /node_modules/,
        use: [
          {
            loader: "babel-loader",
            options: {
              cacheDirectory: true,
              cacheCompression: false,
              compact: false,
            },
          },
        ],
      },
      {
        test: /\.coffee(\.erb)?$/,
        use: [
          {
            loader: "coffee-loader",
          },
        ],
      },
    ],
  },
};

module.exports = merge(webpackConfig, customConfig);

And these are the versions of libraries in the project:

ruby 2.6.5
nodejs 16.13.0
yarn 1.22.15

@rails/webpacker 6.0.0-rc.5
webpack 5.51.1
webpack-cli 4.8.0
css-loader 6.5.1
sass 1.45.1
sass-loader 12.4.0
webpack-dev-server 4.4.0
css-minimizer-webpack-plugin 3.3.1
rails 6.0.3.5

@julian-fullcrum this does not smell like a rails/webpacker issue. Are you on the latest master? If not, first try that.

Next...

https://github.com/rails/webpacker/blob/master/package/rules/sass.js#L3-L16

and

https://github.com/rails/webpacker/blob/master/package/utils/get_style_rule.js#L2-L37

Have all the configuration for sass.

Can you try to customize the sass setting and debug what's causing your issue?

@julian-fullcrum let's reopen if you find that this issue is caused by rails/webpacker.