RE: Importing .scss files inside TS React components with liferay npm bu

Jamie Sammons, modified 3 Years ago. New Member Posts: 2 Join Date: 11/30/21 Recent Posts

Hi Liferay Devs !

I'm trying to build a frontend module that contains React components written in Typescript so they could be reused through multiple portlet modules (so in that way, I don't need to copy each component code in every module that need it). I've got something that is perfectly working and that can be used on other modules by referencing my frontend module on their .npmbundlerrc file but now I'm also trying to use and import seperated .scss for the styling of each component instead of copy/pasting each time the styling in each module's css. After many tries I didn't manage to...

I tried to create a Test component with the following code : 

import React from 'react';

import "./Test.scss";

interface TestProps {
    text: string
}

const Test: React.FC<TestProps> = ({text}) => {

    return <span className="test">{text}</span>
}

export default Test;

As you can see I invoked a .scss that contains the styling for this component. In order to get the scss translated to css and bundled in Liferay JS Loader, I used Liferay NPM Bundler loaders in my .npmbundlerrc file:  

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

However doesn't look like my css is bundled into Liferay JS Loader like it supposed to be according to these loaders documentation. The component's bundled code still invoke the .scss file without Liferay loader. Here's the result in the Test.js built : 

"use strict";

Liferay.Loader.define("test-frontend@1.0.0/components/Test", ['module', 'exports', 'require', 'liferay!frontend-js-react-web$react', './Test.scss'], function (module, exports, require) {
  var define = undefined;
  var global = window;
  {
    Object.defineProperty(exports, "__esModule", {
      value: true
    });
    exports["default"] = void 0;

    var _react = _interopRequireDefault(require("liferay!frontend-js-react-web$react"));

    require("./Test.scss");

    function _interopRequireDefault(obj) {
      return obj && obj.__esModule ? obj : { "default": obj };
    }

    var Test = function Test(_ref) {
      var text = _ref.text;
      return (/*#__PURE__*/_react["default"].createElement("span", {
          className: "test"
        }, text)
      );
    };

    var _default = Test;
    exports["default"] = _default;
    //# sourceMappingURL=Test.js.map
  }
});
//# sourceMappingURL=Test.js.map

So in the end, my css is not invoked and actually my component is not working as it's trying to import something that as not define in the loader and so doesn't exists. I've got the following error in my browser : 

Error: Unsatisfied dependency: ./Test.scss found in module test-frontend@1.0.0/components/Test
    at loader.js:689:15
    at Array.map (<anonymous>)
    at loader.js:671:59
    at Array.forEach (<anonymous>)
    at e.value (loader.js:633:34)
    at loader.js:414:10

Do you have any idea of would be wrong ? I still would like to build this using liferay-npm-bundler (I don't want to use liferay-npm-script)

Some additional hints on how my module is built : 

- I didn't create this module using Yeoman Liferay JS Generator and for some other technical reasons, I can't. It must be a classic module with .bnd file. I created it using Blade command line

- Before running the liferay-npm-bundler command the .tsx file are built using Babel 7, here the npm command used when deploying the module : 

tsc && babel --source-maps -d build/resources/main/META-INF/resources src/main/resources/META-INF/resources --extensions \".ts,.tsx,.js,.jsx\" && liferay-npm-bundler

 Thanks a lot in advance for all you replies. 

thumbnail
Jamie Sammons, modified 3 Years ago. New Member Posts: 13 Join Date: 4/13/20 Recent Posts

Hi, 

Did you install the dev dependencies necessary for the loaders?

You can see the step by step here: 

https://liferay.dev/es/blogs/-/blogs/how-to-use-sass-in-react-widget-liferay-1

Regards,