Search code examples
javascriptwebpackbabeljsgatsbybabel-loader

Building Gatsby components using Webpack cannot transpile Gatsby module


I am trying to make a library of Gatsby components (using specific Gatsby library rather than general React components).

I have been compiling using just babel but I want to be able to translate any CSS-in-JS and do other things so I am trying to build using Webpack.

When I try to compile the Gatsby component it fails in the Gatsby module. I know Gatsby is untranspiled ES6 so I included node_modules in my webpack configuration to transpile but I still:

ERROR in ./node_modules/gatsby/cache-dir/gatsby-browser-entry.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
SyntaxError: /Users/kylecalica/Code/gatsby-learn/gatsby-components/node_modules/gatsby/cache-dir/gatsby-browser-entry.js: Unexpected token (25:4)

  23 | 
  24 |   return (
> 25 |     <React.Fragment>
     |     ^
  26 |       {finalData && render(finalData)}
  27 |       {!finalData && <div>Loading (StaticQuery)</div>}
  28 |     </React.Fragment>

Webpack:

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const htmlWebpackPlugin = new HtmlWebpackPlugin({
  filename: "index.html"
});

module.exports = {
  entry: path.join(__dirname, "/src/index.js"),
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, "/webpack/dist")
  },
  module: {
    rules: [
      {
       test: /\.(js|jsx)$/,
       use: {
         loader: "babel-loader"
       }
     },
     {
       test: /\.css$/,
       use: ['style-loader', 'css-loader']
     },

   ]
  },
  plugins: [htmlWebpackPlugin],
  devServer: {
   contentBase: path.join(__dirname, "dist"),
   port: 9000,
   open: true
 }
};

I am currently trying to take what Gatsby says to do to Storybook in my code but it's hard to figure out how to translate this from their strange way into mine?

Storybook's way of webpack:

module.exports = ({ config }) => {
  // Transpile Gatsby module because Gatsby includes un-transpiled ES6 code.
  config.module.rules[0].exclude = [/node_modules\/(?!(gatsby)\/)/]

  // use installed babel-loader which is v8.0-beta (which is meant to work with @babel/core@7)
  config.module.rules[0].use[0].loader = require.resolve("babel-loader")

  // use @babel/preset-react for JSX and env (instead of staged presets)
  config.module.rules[0].use[0].options.presets = [
    require.resolve("@babel/preset-react"),
    require.resolve("@babel/preset-env"),
  ]

  config.module.rules[0].use[0].options.plugins = [
    // use @babel/plugin-proposal-class-properties for class arrow functions
    require.resolve("@babel/plugin-proposal-class-properties"),
    // use babel-plugin-remove-graphql-queries to remove static queries from components when rendering in storybook
    require.resolve("babel-plugin-remove-graphql-queries"),
  ]

  // Prefer Gatsby ES6 entrypoint (module) over commonjs (main) entrypoint
  config.resolve.mainFields = ["browser", "module", "main"]

  return config
}

.babelrc :

{
  "presets": [
    "babel-preset-gatsby-package",
    "@babel/preset-react",
    "@babel/preset-env"
    ]
}

Solution

  • I solved this by converting what Storybook's webpack module had. I am still putting it through testing however but it compiles fine for now:

    const path = require("path");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    const htmlWebpackPlugin = new HtmlWebpackPlugin({
      filename: "index.html"
    });
    
    module.exports = {
      entry: path.join(__dirname, "/src/index.js"),
      output: {
        filename: 'index.js',
        path: path.resolve(__dirname, "webpack")
      },
      module: {
        rules: [
          {
           test: /\.(js|jsx)$/,
           use: {
             loader: "babel-loader",
             options: {
               presets: ["babel-preset-gatsby-package"],
               plugins: ["@babel/plugin-proposal-class-properties"]
             },
           },
           exclude: [/node_modules\/(?!(gatsby)\/)/],
         },
         {
           test: /\.css$/,
           use: ['style-loader', 'css-loader']
         },
    
       ]
      },
      plugins: [htmlWebpackPlugin],
      devServer: {
       contentBase: path.join(__dirname, "dist"),
       port: 9000,
       open: true
     }
    };