glromeo / esbuild-sass-plugin

esbuild plugin for sass
MIT License
155 stars 40 forks source link

Trouble using importMapper #141

Closed yangtheman closed 1 year ago

yangtheman commented 1 year ago

Hi,

I am trying to migrate from using Rails/webpacker to Rails/jsbundling/esbuild, and I have this particular issue with importMapper.

In our current tsconfig.json, we have path configured like the following.

{
  "compilerOptions": {
    .....
    "paths": {
      "DesignSystem/*": ["app/javascript/design_system/*"],
      "Shared/*": ["app/javascript/shared/*"],
    },
    .....
  },

And in various scss files, we import them by stating and it works fine.

@import 'DesignSystem/colors/_colors.scss';

Now with esbuild and esbuild-sass-plugin, I have the following in esbuild.config.js,

const path = require('path')
const sassPlugin = require("esbuild-sass-plugin").default;

require("esbuild").build({
  ....
  tsconfig: path.join(process.cwd(), "tsconfig.json"),
  outdir: path.join(process.cwd(), "app/assets/builds"),
  absWorkingDir: path.join(process.cwd(), "app/javascript"),
  watch: process.argv.includes("--watch"),
  plugins: [
    sassPlugin({
      loadPaths: [
        "app/javascript/design_system/",
        "app/javascript/shared/"
      ],
      importMapper: (path) => {
        let transformed = path
        if (path.match(/^DesignSystem\//)) {
          transformed = path.replace(/^DesignSystem\//, 'app/javascript/design_system/'); 
        } else if (path.match(/^Shared\//)) {
          transformed = path.replace(/^Shared\//, './app/javascript/shared/');
        };

        console.log(`Received ${path} --> converting to ${transformed}`);
        return transformed
      },
    })
  ],
  define: {
    "global": "window"
  },
  loader: {
    ".js": "jsx",
    ".locale.json": "file",
    ".json": "json",
    ".png": "file",
    ".jpeg": "file",
    ".jpg": "file",
    ".svg": "file",
  }
}).catch(() => process.exit(1))

But, when I run yarn build, I still get the Can't find stylesheet to import error.

✘ [ERROR] [plugin sass-plugin] Can't find stylesheet to import.
  ╷
1 │ @import 'DesignSystem/colors/_colors.scss';
  │         ^^^^^^^^^^^^^^^^^^^^^^^^^^
  ╵

But I do see the console log:

Received DesignSystem/colors/_colors.scss --> converting to app/javascript/design_system/colors/_colors.scss

I feel like there is something obvious I am missing here. If you please point the obvious (or not so obvious) mistake(s), I would really appreciate it.

Thank you in advance!

yangtheman commented 1 year ago

Answering my own question, using path.resolve(__dirname, "") worked for me.

      importMapper: (path) => {
        let transformed = path
        if (path.match(/^DesignSystem\//)) {
          transformed = path.replace(/^DesignSystem\//, path.resolve(__dirname, "") + '/app/javascript/design_system/'); 
        } else if (path.match(/^Shared\//)) {
          transformed = path.replace(/^Shared\//, path.resolve(__dirname, "") + '/app/javascript/shared/');
        };

        console.log(`Received ${path} --> converting to ${transformed}`);
        return transformed
      },
glromeo commented 1 year ago

sorry for the late reply... what you did works. The path resolution would be done by the plugin for you because the importMapper is called before... the catch was that by starting your replaced path with app/ that wasn't a correct relative import and so it wasn't resolved. I see that you would have an harder life relying on the plugin resolution because it's relative to the importing file so your solution seems to me to be the ideal one The ifs are useless though... just invoke both replace...they don't do anything when they don't match and the complexity is the same... also calculate path.resolve(__dirname, 'app/javascript/shared/') once and store it outside of the loop