Metro Bundler in Web
Tags: reactnative, node
Published: 2019-02-27 13:08:56

---
title: Metro Bundler in Web
published: true
description: Use Metro Bundler in Web!
tags: react-native, node
---

## 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.

{% twitter 1088628642970783744 %}
{% twitter 1088711186424758272 %}
{% twitter 1088825340829421569 %}

Hahaha, I couldn't believe it!
Because [The document](https://facebook.github.io/metro/) 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](https://facebook.github.io/metro/docs/en/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](https://facebook.github.io/metro/docs/en/getting-started.html).

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


```js
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.

```html
<!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.

```js
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!