# @openovate/webpack-react-router

> Webpack powered React router that supports virtual modules, virtual folders, and code splitting.

Latest version **0.0.3** (published 2019-09-23) · MIT license · 0 weekly downloads

> **Deprecated.** This package is deprecated.

## Install

```sh
npm install @openovate/webpack-react-router
pnpm add @openovate/webpack-react-router
yarn add @openovate/webpack-react-router
bun add @openovate/webpack-react-router
```

## Health

**Score 10/100 (F)** — status: deprecated.

Negative: deprecated.

## Facts

| | |
|---|---|
| Version | 0.0.3 |
| Published | 2019-09-23 |
| First published | 2019-09-22 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 2 |
| Unpacked size | 19.5 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 0 |
| Author | Christian Blanquera |
| Maintainers | cblanquera |
| Keywords | webpack plugin, react router |

## Links

- npm: https://www.npmjs.com/package/@openovate/webpack-react-router
- Repository: https://github.com/Openovate/webpack-react-router
- Homepage: https://github.com/Openovate/webpack-react-router#readme
- Issues: https://github.com/Openovate/webpack-react-router/issues
- npm.io page: https://npm.io/package/@openovate/webpack-react-router

## Dependencies (2)

- [path-to-regexp](https://npm.io/package/path-to-regexp.md) ^3.1.0
- [webpack-virtual-modules](https://npm.io/package/webpack-virtual-modules.md) ^0.1.11

## Alternatives

- [express-promise-router](https://npm.io/package/express-promise-router.md) — 736.1K weekly downloads
- [next-usequerystate](https://npm.io/package/next-usequerystate.md) — 29.8K weekly downloads
- [@bitkyc08/opencodex](https://npm.io/package/@bitkyc08/opencodex.md) — 4.6K weekly downloads
- [lynkr](https://npm.io/package/lynkr.md) — 575 weekly downloads
- [baremetal.js](https://npm.io/package/baremetal.js.md) — 42 weekly downloads

## Recent versions

- 0.0.3 (latest) — 2019-09-23
- 0.0.1 — 2019-09-22

## README

# webpack-react-router

Webpack powered React router that supports virtual modules, virtual folders,
and code splitting.

## Install

```bash
$ npm install --save-dev @openovate/webpack-react-router
$ npm install --save-dev history
```

Additionally you may want to make sure your react environment is properly setup.
If your doing this from scratch, install the following modules as well.

```bash
$ npm i --save-dev @babel/core @babel/plugin-syntax-dynamic-import  @babel/plugin-transform-react-jsx @babel/polyfill @babel/preset-env @babel/preset-react @babel/register babel-loader react react-dom webpack webpack-cli webpack-dev-server webpack-hot-middleware
```

Also make sure you add the following scripts in `package.json`

```json
{
  "scripts": {
    "build": "webpack",
    "start": "webpack-dev-server --mode development --no-inline"
  }
}
```

## Usage

Create a file called `webpack.config.js` in your project root.

```js
//#FILE: webpack.config.js
const path = require('path');
const ReactRouterPlugin = require('@openovate/webpack-react-router');

module.exports = {
  mode: 'development',
  entry: {
    index: './client/index.js'
  },
  output: {
    filename: '[name].bundle.js',
    publicPath: '/',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: { presets: ['@babel/env'] }
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  },
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    compress: false,
    port: 3000,
    hot: false
  },
  resolve: {
    extensions: ['*', '.js', '.jsx']
  },
  plugins: [
    new ReactRouterPlugin({
      router: 'client/router.js',
      routes: {
        '/': './Hello.jsx',
        '/about': './About.jsx'
      }
    })
  ]
};
```

You will also need to create a `.babelrc` file in your project root.

```json
{
  "presets": ["@babel/env", "@babel/preset-react"],
  "plugins": [
    "@babel/plugin-transform-react-jsx",
    "@babel/plugin-syntax-dynamic-import"
  ]
}
```

Create a file called `dist/index.html` in your project root.

```html
<!DOCTYPE html>
<html>
  <head>
    <meta charSet="utf-8" />
    <title>Webpack React Router</title>
  </head>
  <body>
    <div id="root"></div>
    <noscript>
      You need to enable JavaScript to run this app.
    </noscript>
    <script src="/index.bundle.js"></script>
  </body>
</html>
```

Create a file called `client/index.js` in your project root.

```js
//#FILE: client/index.js
import React from 'react'
import ReactDOM from 'react-dom'
import router from './router'

const { createBrowserHistory } = require('history');

ReactDOM.render(
  router(createBrowserHistory()),
  document.getElementById('root')
)
```

`./router` is a virtual React component generated by this plugin. It requires
that you use the [history](https://www.npmjs.com/package/history) module or
equivalent interface.

Create a component file called `client/Hello.jsx`.

```js
//#FILE: client/Hello.jsx
import React from 'react'
import Link from './Link'

export default class Hello extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello World</h1>
        <ul>
          <li><Link to="/" history={this.props.history}>Home</Link></li>
          <li><Link to="/about" history={this.props.history}>About Us</Link></li>
        </ul>
      </div>
    )
  }
}
```

The router will pass 2 properties to `this.props`.

 - `history` - which is the initial history was passed in `client/index.js`
 - `route` - which will have the information of the route matched

Create a component file called `client/About.jsx`

```js
//#FILE: client/About.jsx
import React from 'react'
import Link from './Link'

export default class About extends React.Component {
  render() {
    return (
      <div>
        <h1>About World</h1>
        <ul>
          <li><Link to="/" history={this.props.history}>Home</Link></li>
          <li><Link to="/about" history={this.props.history}>About Us</Link></li>
        </ul>
      </div>
    )
  }
}
```

Lastly, we need to create a component file called `client/Link.jsx`

```js
//#FILE: client/Link.jsx
import React from 'react';

export default class Link extends React.Component {
  constructor(props) {
    super(props);
    //quirk that is recommended by react. lame.
    this.handle = this.handle.bind(this);
  }

  handle(event) {
    const { to, history } = this.props
    const props = this.props.props || {}

    event.preventDefault();

    history.push(to, props);
    return false;
  }

  render() {
    const { to, children } = this.props;
    const props = { href: to, onClick: this.handle };
    return React.createElement('a', props, children);
  }
}
```

Run `$ npm start` in terminal and open `127.0.0.1:3000` in your browser.

### More Usage

see `test/env` in this repo for advance usage.

## Route Paths

This plugin uses [path-to-regexp](https://www.npmjs.com/package/path-to-regexp)
which is used by [react router](https://www.npmjs.com/package/react-router) and
[express](https://www.npmjs.com/package/express)

## Why

Needed a react router that considered the following.

 - Un-opinionated file structure which [Next.js](https://github.com/zeit/next.js/issues/4789) and [Razzle](https://github.com/jaredpalmer/razzle-unrouted) suffer from.
 - [Virtual Modules](https://www.npmjs.com/package/webpack-virtual-modules)
 - [Virtual Folders](https://www.npmjs.com/package/@openovate/webpack-virtual-folders)
 - [Code Splitting](https://webpack.js.org/guides/code-splitting/)

### Dynamic Imports with Dynamic Pathing

The following example underlies this topic.

```js
const routes = {
  '/': './screens/Hello.jsx',
  '/about': './screens/About.jsx'
}

import(routes['/']).then(component => {
  console.log(component.default)
})
```

Using dynamic `import()` in webpack 4 enables code splitting. When using dynamic
pathing like the above, `import(routes['/'])` simply won't work because webpack
could not predetermine the actual value when compiling.

For some reason, wrapping a JS template seems to work like the following.

```js
import(`${routes['/']}`).then(component => {
  console.log(component.default)
})
```

But for [Virtually Defined Modules](https://www.npmjs.com/package/webpack-virtual-modules),
this does not. Virtual Modules powers [Virtual Folders](https://www.npmjs.com/package/@openovate/webpack-virtual-folders). Virtual Folders allows folder resolution where webpack cannot find
files at their specified location. With Virtual Folders, we could simply tell
Webpack other places where it could be. This is ideal in the case where you may
want to modularize your project using a particular file structure in an
unopinionated way.

For the reasons above, a plugin that generates a virtual router was decided.

---
_Source: https://npm.io/package/@openovate/webpack-react-router · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
