Skip to content Skip to sidebar Skip to footer

Import Css File Into Es6 Returns String Instead Of Object

TL;DR I'm importing a css file into a typescript module, but the import resolves to a string instead of an object. Can anyone tell me why I don't get an object?? Example // preview

Solution 1:

I think you have mistake in your Webpack config. You have nested rules property, instead you should have use:

{
    rules: [
      {
        test: /\.css$/i,
        use: ["style-loader", "css-loader"],
      },
    ],
  }

https://webpack.js.org/loaders/css-loader/

Solution 2:

I'm sorry, but I have to revert my last statement. My issue has NOT been resolved by @Akxe's comment. Now my import statement (import * as test from '...') resolves to an object, but it's still not correct.

I have set up a GIT Repo to reproduce the issue. The readme.md file explains the repro and the issue.

It looks like Webpack is not executing/evaluating the return value of the loader.

Btw. this is not just the case with the css-loader. The result stays the same for raw-loader, sass-loader, style-loader, etc.

My final goal is to lazily load my theme files into a storybook. I try to follow the documentation of the @etchteam/storybook-addon-css-variables-> theme.

Solution 3:

Finally I got my issue solved!

Analysis

The main issue here is the webpack configuration generated by the @angular-devkit/build-angular package. I was able to analyze it by debugging a fresh angular12 application (you can check it out here).

By setting a break-point at /node_modules/@angular-devkit/build-angular/src/utils/webpack-browser-config.js, function: generateWebpackConfig(...), I could inspect the final webpackConfig object in the debugger.

The relevant rule looks like this:

The important part here is the rule setting the module type to asset/source, instructing webpack not to evaluate the loader's result.

webpackConfig object

Solution concept 1: inline loader

With the help of alexander-kait and his great hints at this issue, I was able to find an inline-loader syntax that overrides webpack's module declaration:

importTestfrom'test.css.webpack[javascript/auto]!=!!!style-loader?injectType=lazyStyleTag!css-loader!./test.css';

console.log(typeofTest); // output: objectconsole.log(Test); // output: Object { use: () => void, unuse: () => void }Test.use(); // this should usually be called by a theme switcher...

I'm not really sure about the url pattern here, as it seems to be an undocumented feature, but I assume that it's something like <query-pattern>.webpack[<module-type>]!=!<loaders><query>.

However, since this is an undocumented feature, I was rather reluctant to use it.

Solution concept 2: webpackConfig customization

Since I'm in a storybook context, I decided to customize the webpack configuration according to the storybook documentation.

My solution requires to set up a naming convention (e.g. *.theme.css).

// .storybook/main.jsmodule.exports = {
  webpackFinal: async (config) => {

    // exclude *.theme.css from the *.css ruleset
    config.module.rules.find(rule =>'.css'.match(rule.test)).exclude = [ /\.(?:theme\.css)$/i ];

    // add a rule for *.theme.css
    config.module.rules.push({
      test: /\.(?:theme\.css)$/i,
      use: [
        { loader: 'style-loader', options: { injectType: 'lazyStyleTag' } },
        'css-loader',
      ],
    });
  },
};

With these rules in place, I can now simply do the following:

// preview.jsimportLightThemefrom'./light.theme.css';
importDarkThemefrom'./dark.theme.css';

setupThemeSwitcher(LightTheme, DarkTheme);

Please note that the setupThemeSwitcher function is just pseudocode merely there for the example. In reality I'm using the @etchteam/storybook-addon-css-variables-theme addon...

Solution 4:

I had a very similar issue with storybook and this extension, except l’m loading .scss files. I simply adapted solution 2 to suit my .scss case and it works like a charm. I couldn’t make solution 1 to work, but as stated, it sounds hacky whereas solution 2 is cleaner in my opinion. Thanks a lot for sharing this solution, I was struggling for hours.

Post a Comment for "Import Css File Into Es6 Returns String Instead Of Object"