Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React-leaflet: nullish coalescing operator error #58

Closed
a1exymoroz opened this issue Jan 16, 2022 · 5 comments
Closed

React-leaflet: nullish coalescing operator error #58

a1exymoroz opened this issue Jan 16, 2022 · 5 comments

Comments

@a1exymoroz
Copy link

a1exymoroz commented Jan 16, 2022

Hi,
I have a question about a webpack config. I would be grateful if you could help me)

I've installed react-leaflet in my project and got this error.
image

I found a solution.
PaulLeCam/react-leaflet#883

But don't know how to add the babel plugin to the webpack config.
https://babeljs.io/docs/en/babel-plugin-proposal-nullish-coalescing-operator

Thanks)

Config
let baseConfig = {
target: 'web',
mode: 'development',
devtool: 'source-map',
resolve: {
  extensions: ['.ts', '.tsx', '.js'],
  modules: ['node_modules'],
},
context: path.resolve(__dirname),
module: {
  rules: [
    {
      test: /\.tsx?$/,
      loader: 'ts-loader',
      options: {
        transpileOnly: true,
        compilerOptions: {
          declarationMap: false,
          noEmit: false,
        },
      },
      exclude: /node_modules/,
    },
    {
      use: [
        {
          loader: '@microsoft/loader-cased-file',
          options: {
            name: '[name:lower]_[hash].[ext]',
          },
        },
      ],
      test: /\.(jpe?g|png|woff|eot|ttf|svg|gif|dds)$/i,
    },
    {
      use: [
        {
          loader: 'html-loader',
        },
      ],
      test: /\.html$/,
    },
    {
      test: /\.css$/,
      use: [
        {
          loader: '@microsoft/loader-load-themed-styles',
          options: {
            async: true,
          },
        },
        {
          loader: 'css-loader',
        },
      ],
    },
    {
      test: function(fileName) {
        return fileName.endsWith('.module.scss'); // scss modules support
      },
      use: [
        {
          loader: '@microsoft/loader-load-themed-styles',
          options: {
            async: true,
          },
        },
        'css-modules-typescript-loader',
        {
          loader: 'css-loader',
          options: {
            modules: {
              localIdentName: '[local]_[hash:base64:8]',
            },
          },
        }, // translates CSS into CommonJS
        'sass-loader', // compiles Sass to CSS, using Node Sass by default
      ],
    },
    {
      test: function(fileName) {
        return !fileName.endsWith('.module.scss') && fileName.endsWith('.scss'); // just regular .scss
      },
      use: [
        {
          loader: '@microsoft/loader-load-themed-styles',
          options: {
            async: true,
          },
        },
        'css-loader', // translates CSS into CommonJS
        'sass-loader', // compiles Sass to CSS, using Node Sass by default
      ],
    },
  ],
},
plugins: [
  new ForkTsCheckerWebpackPlugin({
    tslint: true,
  }),
  new ClearCssModuleDefinitionsPlugin(),
  new webpack.DefinePlugin({
    'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
    'process.env.DEBUG': JSON.stringify(true),
    DEBUG: JSON.stringify(true),
  }),
],
devServer: {
  hot: false,
  contentBase: resolve(__dirname),
  publicPath: host + '/dist/',
  host: 'localhost',
  port: port,
  disableHostCheck: true,
  historyApiFallback: true,
  open: true,
  writeToDisk: false,
  openPage: host + '/temp/workbench.html',
  stats: {
    preset: 'errors-only',
    colors: true,
    chunks: false,
    modules: false,
    assets: false,
  },
  proxy: {
    // url re-write for resources to be served directly from src folder
    '/lib/**/loc/*.js': {
      target: host,
      pathRewrite: {
        '^/lib': '/src',
      },
      secure: false,
    },
  },
  headers: {
    'Access-Control-Allow-Origin': '*',
  },
  https: {
    cert: CertificateStore.instance.certificateData,
    key: CertificateStore.instance.keyData,
  },
},
};
@s-KaiNet
Copy link
Owner

Hello,
were you able to have it working with just a regular "gulp serve"?

@a1exymoroz
Copy link
Author

Hello, were you able to have it working with just a regular "gulp serve"?

No. It doesn't work.
I am using your spfx-fast-serve library. And I prefer to work through your library because it's fast

@s-KaiNet
Copy link
Owner

fast-serve is just an "extension" on top of the SPFx, it means that you should make the SPFx build work first. You cannot package your solution for production with fast-serve only, thus you have to set up OOB build anyway.

I took a look at the library you mentioned and tried to implement the suggested workaround on top of the SPFx. I haven't found any other way except adding babel to SPFx to transpile the leaflet sources (like in the linked issue).

So the process of "enabling" leaflet with SPFx and fast-serve is:

  1. Install all dependencies:

     npm install leaflet --save
     npm install react-leaflet --save # you may need --legacy-peer-deps since react@17 is required, but it looks like it works with 16.13 too
     npm install -D @types/leaflet babel-loader @babel/core @babel/preset-env @babel/plugin-proposal-nullish-coalescing-operator
  2. Modify gulpfile.js:

build.configureWebpack.mergeConfig({
  additionalConfiguration: (generatedConfiguration) => {

    generatedConfiguration.module.rules.push(
      {
        test: /node_modules[\/\\]@?react-leaflet[\/\\].*.js$/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              ['@babel/preset-env', { targets: "defaults" }]
            ],
            plugins: ['@babel/plugin-proposal-nullish-coalescing-operator']
          }
        }
      }
    );

    return generatedConfiguration;
  }
});

The above config adds babel-loader for all react-leaflet related .js files.
3. Add leaflet styles: import "leaflet/dist/leaflet.css";
4. Implement the map:

<MapContainer center={[51.505, -0.09]} zoom={13} scrollWheelZoom={false} style={{
height: "400px"
}}>
<TileLayer
  attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
  url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
</MapContainer>
  1. And finally add fast-serve support by modifying webpack.extend.js:
const transformConfig = function (initialWebpackConfig) {
  // transform the initial webpack config here, i.e.
  // initialWebpackConfig.plugins.push(new webpack.Plugin()); etc.

  initialWebpackConfig.module.rules.push(
    {
      test: /node_modules[\/\\]@?react-leaflet[\/\\].*.js$/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: [
            ['@babel/preset-env', { targets: "defaults" }]
          ],
          plugins: ['@babel/plugin-proposal-nullish-coalescing-operator']
        }
      }
    }
  );

  return initialWebpackConfig;
}

With this setup, it works with gulp serve and fast-serve as well.

For simplicity, I pushed a configured solution here.

@a1exymoroz
Copy link
Author

It works!👍
Thank you very much!)💃

@dennisat
Copy link

dennisat commented Feb 4, 2022

The dist code should be ES5 without needing special loaders.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants