LoginSignup
5
1

More than 3 years have passed since last update.

Riot.js Advent Calendar 2019 の5日目が空いていたので埋めます。

Riot Router

Riot.jsv4になったことでRiot Routerも新しくなっていたので再入門します。
https://github.com/riot/route

インストールはnpm i -S @riotjs/route

簡単なサンプル

まずは簡単なコードから試していきます。

index.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Riot Router</title>
</head>
<body>
  <div id="app"></div>
  <script src="./scripts/bundle.js"></script>
</body>
</html>
index.js
import { component, register } from 'riot'
import { Router, Route } from '@riotjs/route'
import App from './app.riot'
import Hello from './hello.riot'
import Goodbye from './goodbye.riot'

// グローバルコンポーネントとして登録
register('my-router', Router);
register('my-route', Route);
register('my-hello', Hello);
register('my-goodbye', Goodbye);

// グローバルに登録せずに直接コンポーネントを生成&マウント
component(App)(document.getElementById('app'));
app.riot
<my-app>
  <my-router>
    <nav>
      <ul>
        <li><a href="/">Home</a></li>
        <li><a href="/hello">Hello</a></li>
        <li><a href="/goodbye">Goodbye</a></li>
      </ul>
    </nav>

    <my-route path="/">
      Welcome to home
    </my-route>
    <my-route path="/hello">
      <my-hello></my-hello>
    </my-route>
    <my-route path="/goodbye">
      <my-goodbye></my-goodbye>
    </my-route>
  </my-router>
</my-app>
hello.riot
<my-hello>
  <p>Hello World!!</p>
</my-hello>
goodbye.riot
<my-goodbye>
  <p>Goodbye World!!</p>
</my-goodbye>

私はWebpackを使っていますが、ここから下はお好みで。

package.json
{
  "name": "riotv4-router-sample",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack --mode production --devtool source-map",
    "start": "webpack-dev-server --inline --watch --hot --colors --content-base app/ --open-page index.html -d --port 4500"
  },
  "keywords": [],
  "author": "KAJIKEN <kentaro@kajiken.jp> (http://kajiken.jp)",
  "license": "MIT",
  "dependencies": {
    "@riotjs/route": "^4.1.0"
  },
  "devDependencies": {
    "@babel/core": "^7.7.2",
    "@babel/preset-env": "^7.7.1",
    "@riotjs/compiler": "^4.5.2",
    "@riotjs/hot-reload": "^4.0.0",
    "@riotjs/webpack-loader": "^4.0.1",
    "babel-loader": "^8.0.6",
    "riot": "^4.6.6",
    "webpack": "^4.41.2",
    "webpack-cli": "^3.3.10",
    "webpack-dev-server": "^3.9.0"
  }
}
webpack.config.js
const path = require('path')

module.exports = {
  mode: 'development',
  //mode: 'production',

  entry: './src/scripts/index.js',
  output: {
    path: path.resolve(__dirname, 'app/scripts'),
    filename: 'bundle.js',
    publicPath: '/scripts/',
  },

  devtool: 'inline',
  //devtool: 'source-map',

  module: {
    rules: [
      {
        test: /\.riot$/,
        exclude: /node_modules/,
        use: [{
          loader: '@riotjs/webpack-loader',
          options: {
            hot: true, // set it to true if you are using hmr
            // add here all the other @riotjs/compiler options riot.js.org/compiler
            // template: 'pug' for example
          }
        }]
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      }
    ]
  }
}
.babelrc
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "modules": false,
        "targets": [
          ">0.25%",
          "not ie 11",
          "not op_mini all"
        ]
      }
    ]
  ]
}
ディレクトリ構成
.
│  .babelrc
│  package.json
│  webpack.config.js
│  
├─app
│  │  index.html
│  │  
│  └─scripts
│          bundle.js
│          bundle.js.map
│          
├─node_modules
│              
└─src
    └─scripts
            app.riot
            goodbye.riot
            hello.riot
            index.js

URLに応じたタグの内容に切り替わることがわかります。
rr1_2019_12_04_130833(slt)(raw).gif

注意点

このままではURLを直接入力した場合はエラーになります。
Web Server側の設定でトップに飛ばすなどすれば回避は可能です。
rr2_2019_12_04_132509(slt)(raw).gif

今回の例ですと、webpack-dev-serverを使っているので、historyApiFallbackオプションを利用します。

package.json(抜粋)
  "scripts": {
    "build": "webpack --mode production --devtool source-map",
    "start": "webpack-dev-server --inline --watch --hot --colors --content-base app/ --open-page index.html --historyApiFallback true -d --port 4500"
  },

historyApiFallback:trueとすることで404 not foundの時にindex.htmlに飛ばされます。

rr3_2019_12_05_170830(slt)(raw).gif

Web Server側で対処できないような場合はハッシュを使いましょう。

app.riot
<my-app>
  <my-router>
    <nav>
      <ul>
        <li><a href="#/">Home</a></li>
        <li><a href="#/hello">Hello</a></li>
        <li><a href="#/goodbye">Goodbye</a></li>
      </ul>
    </nav>

    <my-route path="(/|/#/)">
      Welcome to home
    </my-route>
    <my-route path="/#/hello">
      <my-hello></my-hello>
    </my-route>
    <my-route path="/#/goodbye">
      <my-goodbye></my-goodbye>
    </my-route>
  </my-router>
</my-app>

rr7_2019_12_05_172759(slt)(raw)_2.gif

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1