Search code examples
reactjstypescriptsassrolluprollupjs

Rollup Build failure for SCSS exports to be used in TS ( [!] Error: 'default' is not exported by src/styles/variables.scss )


I'm running into the following rollup build failure where I would like to be able to used exports from a scss file in my typescript files.

The build failure reads as follows:

[!] Error: 'default' is not exported by src/styles/variables.scss, imported by src/components/Layout/Layout.themes.tsx https://rollupjs.org/guide/en/#error-name-is-not-exported-by-module src/components/Layout/Layout.themes.tsx (1:7) 1: import vbl from '../../styles/variables.scss';

My rollup config looks as follows:

import scss from 'rollup-plugin-scss';
import typescript from 'rollup-plugin-typescript2';
import image from '@rollup/plugin-image';
import { terser } from 'rollup-plugin-terser';
import pkg from './package.json';

export default {
  input: ['src/index.tsx'],
  output: [
    {
      file: pkg.main,
      format: 'cjs',
      sourcemap: true,
      name: 'Main'
    },
    {
      file: pkg.module,
      format: 'esm',
      sourcemap: true,
      name: 'tree-shaking'
    }
  ],
  external: [...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.devDependencies || {}), ...Object.keys(pkg.peerDependencies || {})],
  plugins: [image(), scss({ output: 'dist/styles.css' }), typescript({ useTsconfigDeclarationDir: true }), terser()]
};

The variables.scss contains:

// colors
$color-blue: #1c4077;
$color-orange: #e87d1e;

:export {
  colorBlue: $color-blue;
  colorOrange: $color-orange;
}

The variables.scss.d.ts typings file contains:

export interface IGlobalScss {
  colorBlue: string;
  colorOrange: string;
}

export const variables: IGlobalScss;

export default variables;

And the Layout.themes.tsx file reads as follows:

import vbl from '../../styles/variables.scss';

export const myTheme = {
  headerColor: vbl.colorBlue,
  footerColor: vbl.colorOrange
}

I've tried an import of the non-default export import { variables } from '../../styles/variables.scss'; but it fails as well with:

[!] Error: 'variables' is not exported by src/styles/variables.scss, imported by src/components/Layout/Layout.themes.tsx https://rollupjs.org/guide/en/#error-name-is-not-exported-by-module src/components/Layout/Layout.themes.tsx (1:9) 1: import { variables } from '../../styles/variables.scss';

I am able to serve the project via Storybook, however when I build via Rollup I encounter the error listed above. Please assist me in resolving this build failure?

Here is a CodeSandbox for this example. Extract the zip, yarn and run either yarn start or yarn build to test in VSCode. You'll notice that yarn start succeeds whereas yarn build will fail as mentioned above.


Solution

  • I think the problem is that the output property is not false.

    Here is what the plugin does when that property is set to false:

    if (options.output === false) {
      const css = compileToCSS(code)
      return {
        code: 'export default ' + JSON.stringify(css),
        map: { mappings: '' }
      }
    }
    

    and this happens in the transform hook, which is invoked before the parsing takes place. This is important because export default ... is treated as a module, meaning you can import it in your js files.

    So I think you'll have to manually bundle that variables file with:

    scss({ output: false }).
    

    Now, another problem arises: when you import from the .scss file, you'll get the :export object stringified.

    For example:

    "export default ":export {\n  colorBlue: #1c4077;\n  colorOrange: #e87d1e; }\n""
    

    the plugin in use does not seem to handle this case.

    So I think the solution involves manipulating that string so that you'd end up with something like this:

    `{ colorX: 'value', colorY: 'value' }`