analogjs / analog

The fullstack meta-framework for Angular. Powered by Vite and Nitro
https://analogjs.org
MIT License
2.5k stars 240 forks source link

[FEAT] Allow to define `includePaths` in styleOptions for Angular compiler plugin #139

Closed miluoshi closed 1 year ago

miluoshi commented 1 year ago

Which scope/s are relevant/related to the feature request?

vite-plugin-angular

Information

Problem: I want to be able to define custom path aliases for import paths in my scss stylesheets and I am not able to.

Angular+Webpack alternative: @nrwl/angular:webpack-browser executor and Angular CLI allows me to define stylePreprocessorOptions.includePaths to define custom paths (except node_modules) to search for scss modules at.

Solution: createCompilerPlugin function accepts 2nd parameter styleOptions, that can contain includePaths property. That option is consumed by sass plugin.

My proposed solution has two parts:

Please let me know if you are ok with this solution 🙏

Describe any alternatives/workarounds you're currently using

No alternative exists except of patching the package

I would be willing to submit a PR to fix this issue

brandonroberts commented 1 year ago

Thanks @miluoshi. We don't use the sass plugin included with createCompilerPlugin. This is handled by Vite itself. We had a discussion about this here with included solutions for includePaths

https://twitter.com/brandontroberts/status/1581824172547665920

You can fix it in your Vite config

"Fixed the imports by adding includePaths with a relative path to the root of the workspace in the Vite config."

    css: {
      preprocessorOptions: {       
        scss: {
          includePaths: ['node_modules', `../../assets/scss`]
        }
      }
    },
miluoshi commented 1 year ago

Hi @brandonroberts, thanks for your reply! I don't see very deep into the Vite + Angular build system so take my findings with a grain of salt.

TL;DR: css.preprocessorOptions.scss.includePaths doesn't work for me

With the new proposed includePaths plugin option there are together 3 options that influence resolution of aliased sass modules: resolve.alias, css.preprocessorOptions.scss.includePaths and the new proposed option.

After debugging the build pipeline I have found that without the proposed new option our app won't build. I get errors like this:

✘ [ERROR] [plugin angular-sass] Can't find stylesheet to import.
  ╷
1 │ @use 'ui-common-styles/variables/colors';
  │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The option is needed to compile a scss file with custom path alias in angular-cli/packages/angular_devkit/build_angular/src/builders/browser-esbuild/sass-plugin.ts call to sass.compile (@angular-devkit/build-angular@14.2.9). I also needed to define the same custom path in resolve.alias so the vite config looks like this:

// vite.config.ts
import angular from '@analogjs/vite-plugin-angular';
import { workspaceRoot } from '@nrwl/devkit';

const commonStylesLocation = path.resolve(workspaceRoot, 'libs/ui/src/lib');

export default defineConfig(({ mode }) => ({
  resolve: {
  alias: {
    'ui-common-styles': `${commonStylesLocation}/ui-common-styles`,
  },
  plugins: [
    angular({
      includePaths: [commonStylesLocation],
      workspaceRoot,
      inlineStylesExtension: 'scss',
    }),
  ],
});
// libs/ui/src/lib/ui-common-styles/variables/colors.scss
@import 'ui-common-styles/variables/colors';

Maybe it's obvious, but I found it interesting during my debugging session that there are 2 pipelines that process the same sass files in our app. At first the stylesheets are processed by @angular-devkit/build-angular:browser-esbuild builder and then they are processed by Vite's CSS transformer. Maybe it's related to #142?

miluoshi commented 1 year ago

Here's the call sequence for processing scss by @angular-devkit/build-angular:browser-esbuild@14.2.9 :

By following this sequence I can see that passing includePaths to createCompilerPlugin's styleOptions would eventually pass them to createSassPlugin's loadPaths.


Call sequence for Vite CSS transformer vite@3.2.3:

brandonroberts commented 1 year ago

I see. The esbuild compiler plugin is also processing SCSS, along with Vite. The fix seems reasonable to me. I've moved the plugin inside the @analogjs/platform package, so we can add it to the vite options and pass it to both plugins.