DEV Community

loading...

Metro Bundler in Web

sasurau4 profile image sasurau4 ・3 min read

Intro

Do you know Metro Bundler?
If you using React Native, you are familiar with it.
Metro Bundler is the JavaScript bundler for React Native.
I found one tweet about surprising thing about Metro Bundler few month ago.



Hahaha, I couldn't believe it!
Because The document says "The JavaScript Bundler for React Native" at the top.
But Ms. Nakazawa and Mr.Conner are inside Facebook team members and more Mr.Conner is the tech lead for web foundation of Instagram.
So, I checked whether Instagram use metro bundler for web or not.

Checking

Metro Bundler has document about using as CLI, so I bundles some JavaScript files and compare it with web's bundled file.
I found common points like __BUNDLE_START_TIME__=this.nativePerformanceNow?nativePerformanceNow():Date.now().
And enter window._sharedData in Chrome's Developer tools console, you'll find bundle_variant: "metro" that seems the bundle config.

I confirmed Instagram use Metro Bundler for Web. I'm very curious how to do it.
Let's try it!

Using Metro Bundler in Web!

The repo: https://github.com/sasurau4/sample-metro-bundler-in-web

I explain how to use Metro Bundler in Web.

Metro Bundler provides its functions as CLI, server itself and express middleware according to the document.

So, I choose express middleware and the server is following.

const Metro = require('metro');
const express = require('express');
const app = express();

Metro.loadConfig().then(async config => {
  const metroBundlerServer = await Metro.runMetro(config);
  app.use(metroBundlerServer.processRequest.bind(metroBundlerServer));

  app.use('/', express.static('public'));

  const { server: serverConfig } = config;
  const { port } = serverConfig;
  app.listen(port);
});

This server serve static files inside public dir and bundle file bundled by Metro.

The static file is following.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Metro Bundler in Web!</title>
  </head>
  <body>
    <div id="root"></div>
    <script src="index.bundle?platform=web&dev=true&minify=false"></script>
  </body>
</html>

We can get bundle file from the path of index.bundle with various parameters.

If you want to only bundling files, it's all done.

In the real world, we often need to transpile JS files with babel or like that.

It's very easy to use Babel with Metro.

If you want to use React, put the babel.config.js like following.

module.exports = {
  presets: ['@babel/preset-env', '@babel/preset-react'],
  plugins: ['@babel/plugin-proposal-export-default-from'],
};

Run the server and access to localhost, the application run in the browser!
It's all done.🎉

I explain how to use Metro Bundler same like webpack-dev-server.
If you want to deploy artifacts to hosting services, you can do it from cli!

Conclusion

Although Metro Bundler is mainly focus to the React Native, we can also use it for web.
I also learned functions provided by the webpack and webpack-dev-server.
It is rare to use Metro Bundler for web in production today.
I imagine If someday that Metro Bundler is regulary used for web comes true, we could write Universal Application with React Native and React Native Web.
It's exciting future!

Thanks for the Metro team about documentation and maintenance.
Thanks for reading!

Discussion (0)

pic
Editor guide