Strapi v3 and webpack

System Information
  • Strapi Version: 3.6.8
  • Operating System: linux
  • Database: sqlite
  • Node Version: 14
  • NPM Version: 6.14.18
  • Yarn Version: —

This issue is more due to me not understanding fully webpack and the compilation process rather than with Strapi. Anyhow, here is the thing:

I wanted to create a new npm library that i could import across all of my plugins so that i could manage messages based on events.

I called it strapi-events and it contains an index.json, a component and the pub/sub stuff (in node_modules folder obviously):

index.js:

import AlertBox from "./AlertBox";

const subscribe =(eventClass, handler) => {
    let sugar = function (event) {
      handler(...event.detail);
    };
    document.addEventListener(eventClass.name, sugar, { passive: true });
    return {
      unsubscribe: function unsubscribe() {
        document.removeEventListener(eventClass.name, sugar);
      },
    };
  }
  
const publish = (event) => {
    let nativeEvent = new CustomEvent(event.constructor.name, {
        detail: event.args,
    });
    document.dispatchEvent(nativeEvent);
}

class AlertEvent {
    constructor(currentConfiguration) {
        this.args = [currentConfiguration];
    }
}
  

export {
    subscribe,
    publish,
    AlertEvent,
    AlertBox
}

and basically AlertBox.js which is very simple as well:

import React, { useState, useEffect } from "react";
import P from './P'
import { FormattedMessage } from 'react-intl';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faPlay, faPlus, faSave, faTimes, faCog, faPencilAltl, faTrashAlt, faBug, faExclamationTriangle, faCheck, faInfoCircle } from '@fortawesome/free-solid-svg-icons';
import { subscribe } from '../../utils/pubsub';
import { AlertEvent } from '../../utils/alertEvents';
import { Button, Flex, InputNumber, Select, Table } from '@buffetjs/core';
import styled from "styled-components";

const OverlayDiv = styled.div`
  &:before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    background: rgba(0, 0, 0, 0.6);
    z-index: 1051;
  }
`
const OverlayDialog = styled.div`
  background: ${props => props.inputColor || "white"};
  border: #333333 solid 0px;
  color: ${props => props.textColor || "black"};
  text-align: center;
  position: absolute;
  left: 0;
  top: 0;
  z-index: 1052;
  width: 100%;
  height: 4em;
  box-shadow: 0 5px 10px rgb(0 0 0 / 30%);
`

const SpacedDiv = styled.div`
  margin: 0.5em;
  padding:0.5em;
`


const Alert = ({type, text, setVisible}) => {
  switch(type) {
    case 'error':
      return 
        (<OverlayDialog inputColor="#F00" textColor="#FFF">
          <SpacedDiv>
            <FontAwesomeIcon icon={faBug} />
            <strong> Error: </strong> {text} &nbsp;
            <a onClick={()=>setVisible(false)}><FontAwesomeIcon icon={faTimes} /></a>
          </SpacedDiv>
        </OverlayDialog>
      );
      break;
    case 'info':
      return 
        (<OverlayDialog inputColor="#EEE" textColor="#000">
          <SpacedDiv>
            <FontAwesomeIcon icon={faInfoCircle} />
            <strong> Info:</strong>{text} &nbsp;
            <a onClick={()=>setVisible(false)}><FontAwesomeIcon icon={faTimes} /></a>
          </SpacedDiv>
        </OverlayDialog>
      );
      break;
    case 'warning':
      return 
        (<OverlayDialog inputColor="#CA0" textColor="#FEE">
          <SpacedDiv>
            <FontAwesomeIcon icon={faExclamationTriangle} />
            <strong> Warn: </strong>{text} &nbsp;
            <a onClick={()=>setVisible(false)}><FontAwesomeIcon icon={faTimes} /></a>
          </SpacedDiv>
        </OverlayDialog>
      );
      break;
    case 'success':
      return 
        (<OverlayDialog inputColor="#3A5" textColor="#FFF">
          <SpacedDiv>
            <FontAwesomeIcon icon={faCheck} />
            <strong> Success: </strong>{text} &nbsp;
            <a onClick={()=>setVisible(false)}><FontAwesomeIcon icon={faTimes} /></a>
          </SpacedDiv>
        </OverlayDialog>
      );
      break;
  }

}

const AlertBox = () => {

  const [visible, setVisible] = useState(false);
  const [alertData, setAlertData] = useState({type:'info', text:''});

  useEffect(() => {
    const handle = subscribe(AlertEvent, (config) => {
      console.log(config);
      setVisible(config.state === 'open' ? true : false);
      setAlertData(config.data);
    });

    return function cleanup() {
      handle.unsubscribe();
    };
  });

  return visible && (
    <OverlayDiv>
      <Alert type={alertData.type} text={alertData.text} setVisible={setVisible} />
    </OverlayDiv>
  );
};

export default AlertBox;

for completeness i should include the P component:

import React from 'react';
import styled from "styled-components";

const P = styled.p`
  padding: 0.5em;
  color: #444;
`;

export default P

Anyhow, if i try to import those modules in a plugin code, webpack will trip stating that:

Error: ./node_modules/@punch-in/strapi-events/AlertBox/index.js 47:9
Module parse failed: Unexpected token (47:9)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|     case 'error':
|       return 
>         (<OverlayDialog inputColor="#F00" textColor="#FFF">

Now, obviously webpack can compile react code as all of v3 frontend is written on react. There is something wrong but i cannot wrap my head around it.

I tried also compiling my code separately so that it comes ready for use (no idea if this does even make sense at all, however, after writing a new webpack compiler, i get the same error message.

Any pointer (or alternative workaround) will be much appreciated

regards,
Valerio

I kinda copied the logic from strapi-helper-plugin… Used rollup to compile it and it worked. Honestly i don’t know why it did not work with webpack, somebody more expert might be able to help :slight_smile: