Using styled-components in Sage 9

I understand this might not apply directly to Sage 9 but I was hoping someone could help me out. Lint configs are not my strongest suit.

I have my theme working with React and wanted to add the styled-components package. When trying to use styled-components I get the following error:

Module build failed:
7  :     return <Modal />
8  :   }
9  : }
10 :
11 : const Modal = styled.div`
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Tagged template strings are not supported. Use `transforms: { templateString: false }` to skip transformation and disable this error, or `transforms: { dangerousTaggedTemplateString: true }` if you know what you're doing (11:14)

You may use special comments to disable some warnings.
Use // eslint-disable-next-line to ignore the next line.
Use /* eslint-disable */ to ignore all warnings in a file.

Here are my config files:

.babelrc

{
  "presets": ["react", "es2015"],
  "plugins": ["babel-plugin-styled-components"]
}

.eslintrc.js

module.exports = {
  root: true,
  parser: "babel-eslint",
  extends: ['plugin:react/recommended', 'prettier', 'prettier/react', 'airbnb'],
  globals: {
    wp: true,
    it: false,
    expect: false,
    describe: false,
    navigator: false,
  },
  env: {
    node: true,
    es6: true,
    amd: true,
    browser: true,
    jquery: true,
  },
  parserOptions: {
    ecmaFeatures: {
      globalReturn: true,
      generators: false,
      objectLiteralDuplicateProperties: false,
      experimentalObjectRestSpread: true,
    },
    ecmaVersion: 2017,
    sourceType: 'module',
  },
  plugins: ['import', 'react', 'jsx-a11y'],
  settings: {
    'import/core-modules': [],
    'import/ignore': [
      'node_modules',
      '\\.(coffee|scss|css|less|hbs|svg|json)$',
    ],
  },
  rules: {
    'no-console': 0,
    quotes: ['error', 'single'],
    'comma-dangle': [
      'error',
      {
        arrays: 'always-multiline',
        objects: 'always-multiline',
        imports: 'always-multiline',
        exports: 'always-multiline',
        functions: 'ignore',
      },
    ],
    semi: [2, 'never'],
    'react/prop-types': [0],
    'react/destructuring-assignment': [0],
    'no-use-before-define': [0],
    'import/prefer-default-export': [0],
    'react/jsx-filename-extension': ['off'],
    'linebreak-style': ['off'],
    'no-undef': ['error'],
    'react/sort-comp': ['off'],
    'react/prefer-stateless-function': ['off'],
  },
}

I do not have my own webpack config file.

I think this might be an issue with Bublé (what Sage 9 is using instead of Babel). You can enable additional options in resources/assets/build/webpack.config.js:

Seems like this is the option you’ll want to enable:
~~https://buble.surge.sh/guide/#-dangeroustaggedtemplatestring-~~

Maybe try either of these options in your error message:

Tagged template strings are not supported. Use `transforms: { templateString: false }` to skip transformation and disable this error, or `transforms: { dangerousTaggedTemplateString: true }` if you know what you're doing

I was able to get it working by setting the Bublé loader’s options to the following:

           {
             loader: 'buble',
             options: {
               objectAssign: 'Object.assign',
+              transforms: {
+                modules: false,
+                templateString: false,
+              },
             },
           },

Here’s example usage in resources/assets/scripts/routes/common.js:

import React from 'react';
import ReactDOM from 'react-dom';
import styled from 'styled-components';

const Button = styled.button`
  background-color: black;
  color: white;
  padding: 0.5rem 1rem;
  border: 1px solid black;
  transition: 0.2s ease;

  :hover {
    background-color: white;
    color: black;
  }
`;

export default {
  init() {
    ReactDOM.render(
      <div>
        <Button>Hello, World!</Button>
      </div>,
      document.getElementById('root')
    );
  },
  finalize() {
    // JavaScript to be fired on all pages, after page specific JS is fired
  },
};
2 Likes

That did it! Thank you so much.

1 Like