Search code examples
dockerwebpackdocker-composejsxbabel-loader

How to fix Webpack 'You may need an appropriate loader to handle this file type' when running inside a container?


Issue:

The issue is that the moment we start Webpack in a docker container it's not able to find the 'babel-loader` to parse the jsx even though we install the node modules in the container.

Context:

I have a docker-compose setup where I have a set of containers including a website where I run Express that renders a React website.

In the current situation we run de docker-compose and run Webpack on our local develop machines and the build.js files get mapped into the container and nodemon restarts the server. This works.

Because sometimes freelancers/new teammembers join this project their local node/npm versions may result in errors when running on the local machine.

This is why we want to spin up a develop container where we run Webpack and map the build files back to the local machine and into the website container.

Note that I'm not trying to have a webpack-dev-server running, it should just listen for changes in src files and output the build files.

Attempts:

  • Change the node version of the container
  • Updated the node modules to the latest version
  • Install webpack/babel globally in the container

Dockerfile-dev

###############################################################################
# Step 1 : Create a base image
#
FROM node:12.6 as base
WORKDIR /var/www

###############################################################################
# Step 2 : Create all files needed to run the app
#
FROM base as builder
ARG SSH_KEY

COPY ./ /var/www

RUN mkdir /root/.ssh/
RUN echo "$SSH_KEY" > /root/.ssh/id_rsa
RUN chmod 600 /root/.ssh/id_rsa

RUN ssh-keyscan gitlab.com > /root/.ssh/known_hosts

# configure the npm env
RUN npm set progress=false
RUN npm i --no-optional

###############################################################################
# Step 3 : Final image to export
#
FROM base

# Copy files from the build step
COPY --from=builder /var/www/ /var/www

CMD [ "npm", "run", "dev" ]

Docker-compose entry

  develop:
    build:
      context: './site'
      dockerfile: Dockerfile-dev
    image: 'boilerplate-develop'
    container_name: 'boilerplate-develop'
    env_file:
      - ./config/local/.env
    restart: 'unless-stopped'
    volumes:
      - ./site/src:/var/www/src

webpack.config.js

const path = require('path')
const nodeExternals = require('webpack-node-externals')
const {resolve, loaders, plugins,} = require('./webpack/common.config')

const PROD = process.argv.indexOf(`-p`) > 0

const getModule = type => ({
    rules: [
        {
            test: /\.js|jsx?$/,
            exclude: /(node_modules|bower_components|www\/)/,
            use: {
                loader: `babel-loader`,
                options: {
                    babelrc: false,
                    configFile: false,
                    presets: [
                        [
                          '@babel/preset-env',
                          {
                            forceAllTransforms: PROD,
                            modules: false,
                            useBuiltIns: false,
                            debug: false,
                          },
                        ],
                        ['@babel/preset-react', { development: !PROD }],
                    ],
                    plugins: [
                        "@babel/plugin-transform-async-to-generator",
                        "@babel/plugin-proposal-class-properties",
                        "@babel/plugin-transform-destructuring",
                        "@babel/plugin-proposal-object-rest-spread",
                        "@babel/plugin-transform-runtime",
                        ...(!PROD ? [] : ['@babel/transform-react-inline-elements']),
                        ...(!PROD ? [] : ['transform-react-remove-prop-types']),
                        [
                            "module-resolver",
                            {
                                "alias": {
                                    "_scrollPercentage": [
                                        "./src/components/vendor/react-scroll-percentage/react-scroll-percentage.esm.js"
                                    ],
                                    "_components": ["./src/components/components.js"],
                                    "_actionTypes": ["./src/redux/actionTypes.js"],
                                    "_routes": ["./src/components/views/routes.js"],
                                    "_utils": ["./src/utils/utils.js"],
                                    "_view": ["./src/components/views/View.jsx"]
                                }
                            }
                        ]
                    ]
                }
            },
        },
        ...loaders[type],
    ],
})

const client = {
    entry: {
        "js/bundle": [`whatwg-fetch`, `core-js/features/promise`, `./src/client.jsx`,],
        "js/intro": `./src/intro.js`,
        serviceWorker: `./src/service-worker.js`,
    },
    output: {
        path: path.join(__dirname, `src`, `static`),
        filename: PROD ? `[name].[chunkhash].min.js` : `[name].js`,
    },
    resolve,
    module: getModule(`client`),
    plugins: plugins.client,
    stats: 'verbose'
}

const server = {
    target: `node`,
    node: {
        __dirname: false,
    },
    externals: [
        nodeExternals({
            modulesFromFile: true,
        }),
    ],
    entry: {
        js: `./src/server.js`,
    },
    output: {
        path: path.join(__dirname, `src/server/build`),
        filename: PROD ? `server.min.js` : `server.js`,
        libraryTarget: `commonjs2`,
    },
    resolve,
    module: getModule(`client`),
    plugins: plugins.server,
}

module.exports = [client, server,]

Error:

boilerplate-develop |     ERROR in ./src/client.jsx 37:4
boilerplate-develop |     Module parse failed: Unexpected token (37:4)
boilerplate-develop |     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
boilerplate-develop |     |
boilerplate-develop |     | const Client = props => (
boilerplate-develop |     >     <Provider store={store}>
boilerplate-develop |     |         <Router history={history}>
boilerplate-develop |     |             <App {...props} history={history} />
boilerplate-develop |      @ multi whatwg-fetch core-js/features/promise ./src/client.jsx js/bundle[2]

Solution

  • It seems like your volume is mapped to www and you are excluding www in the webpack loader that searches for js and jsx files. Webpack executes the regex commands on the full file path not the relative path.

    Try and remove www from the exlude property and try again.