20201117のNode.jsに関する記事は5件です。

NextJSのapiでサーバー側からリダイレクトをさせたい時

  • page/api配下で処理を書いてそれをfetchした時に、処理内容に応じてクライアント側でリダイレクト処理をさせたい時res.redirect('/')と書いてもstatus: 307が帰ってくるだけでクライアント側はリダイレクトされません。
  • クライアント側のリダイレクトをさせたい時はクライアント側でrouter処理を書きましょう。
src/api/*
export deafult (req, res) => {
  res.status(307)
}
src/pages/*
import Router from 'next/router'

() => {
  if(code == 307){
    Router.push('/')
  }
}

node弱いのでもっといいやり方あったら教えてください。。。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

湯婆婆言語作ってみた

湯婆婆言語作ってみた

Qiitaで湯婆婆のセリフをいかに短く実装するかブームらしいので自作言語を作って
実装した話です
ソースコードはここにのってます
https://github.com/riya81/yuba

うぷ主の環境

  • macOS Big Sur 11.0.1
  • Node 12.16.3

手順
1. 自作言語の構文を考える
2. トランスパイル先の言語を決める
3. ファイルを読みこむ
4. トランスパイラを作る
5. トランスパイラをビルドする

手順は僕の他の記事に詳しく書かれているので省きます
この記事のソースコードを少し変えただけです
https://qiita.com/riya81/items/b1d5261205d13e4740cb

コマンド

y "名前";

これだけで湯婆婆を実装できます
この機能しかないです

まとめ

まとめることなんかほぼ無いうっすい記事ですが以上
湯婆婆言語を作った話でした

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

コピペで簡単!爆速でtailwindcssをNode.jsに導入する方法について

はじめに

皆さんはどのCSSフレームワークを使われていますか?

有名どころは、Twitter社が作ったBootStrapでしょうか。

Bootstrapの大きな欠点は、どこかで見たようなサイトに仕上がり、
デザインにオリジナリティが出すことが難しくなります。

そんな中でおすすめしたいのが、今回取り上げるTailwindです。

この記事では、Node.jsでtailwindcssを導入する方法をご紹介いたします。

今回使用するモジュール

今回使用したモジュールは以下の通りです。
今回採用したテンプレートエンジンはejsとなります。
また、ルーティング処理等はすべてexpressを用いています。

package.json
"autoprefixer": "^10.0.1",
"ejs": "^3.1.5",
"express": "^4.17.1",
"postcss": "^8.1.6",
"postcss-cli": "^8.2.0",
"tailwindcss": "^1.9.6"

[STEP1]プロジェクトを作成し、そのディレクトリに移動しましょう

ターミナル
mkdir nodejs-tailwindcss
cd nodejs-tailwindcss

mkdirでファイルを作成します。
cdでディレクトリを移動します。

[STEP2]初期化処理を行う

ターミナル
npm init

このコードを実行して以下のファイルが作成できればOKです。

package.json
{
    "name": "nodejs-tailwindcss",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
    },
    "author": "",
    "license": "ISC",
}

[STEP3]JavaScriptのファイルを作成する

ターミナル
touch index.js

簡単ですね。
ただindex.jsファイルを作成するだけです。

[STEP4]必要なモジュールをインストールする

ターミナル
npm install express ejs --save

この後、tailwindcssなどのモジュールもインストールしますが、
わかりやすさに重きをおくため、先にexpressとejsをインストールします。

こちらを実行することで、package.jsonが以下のようになればOKです。

package.json
{
    "name": "nodejs-tailwindcss",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
    },
    "author": "",
    "license": "ISC",
    "dependencies": {
        "ejs": "^3.1.5",
        "express": "^4.17.1",
    }
}

[STEP5]expressでルーティング処理等を記述する

STEP3で作成したindex.jsに以下のコードを記述します。

index.js
//モジュールを読み込む
const express = require('express');
const ejs = require('ejs');

//読み込んだexpressモジュールを実体化してインスタンスにする
const app = express();

//テンプレートエンジンとしてejsを用いる(今回はejsを使いません)
app.set('view engine', 'ejs');

//ルーティング処理
app.get('/', (req, res) => {
    res.send("expressを導入しました");
});

//サーバーを立ち上げる
app.listen(3000, () => {
    console.log('http://localhost:3000');
});

[STEP6]tailwindcssなど必要なモジュールをインストールする

ようやく本題のtailwindcssをここでインストールします。
ついでにpostcss, autoprefixerもインストールします。

この2つは解説します。
PostCSSとは、Node.js製の「CSSツールを作るためのフレームワーク」です。
Autoprefixerベンダープリフィックスを自動で付与するPostCSS製のツールです。

tailwindcssはPostCSSのプラグインであるため、
最新のCSSをブラウザが理解できるものに変換するツールが必要となります。

ということで、コマンドラインからPostCSSを扱える, postcss-cliを合わせた4つをインストールしましょう。

ターミナル
npm install tailwindcss postcss autoprefixer postcss-cli --save

[STEP7]tailwindcssを使うために必要なファイルを作成する

これが最後のステップです。
何個かファイルを作成しないといけないのでまずはやるべきことを下記に記載します。

  • tailwind.config.jsの作成
  • postcss.config.jsの作成とファイルへの記述
  • CSSを格納するフォルダ・ファイルを作成
  • package.jsonにCSSをビルドする記述を追加

tailwind.config.jsの作成

ターミナル
npx tailwindcss init

このファイルは特にいじる必要はありません。
カスタマイズをする時にでも記載しましょう。
詳しくはこちらをご確認ください。

postcss.config.jsの作成とファイルへの記述

ターミナル
touch postcss.config.js

こちらを実行すると、postcss.config.jsが作成されます。
こちらのファイルに以下の記述を追加してください。

postcss.config.js
module.exports = {
    plugins: [require('tailwindcss'), require('autoprefixer')],
};

CSSを格納するフォルダ・ファイルを作成

ターミナル
mkdir public
mkdir public/styles
touch public/styles/tailwind.css
touch public/styles/style.css

上から順に、
publicフォルダを作成
②publicフォルダ内にstylesフォルダを作成
③stylesフォルダ内にstyle.cssファイルを作成
④stylesフォルダ内にtailwind.cssファイルを作成

④のtailwind.css内には以下の記述を追加してください。

tailwind.css
@tailwind base;
@tailwind components;
@tailwind utilities;

package.jsonにCSSをビルドする記述を追加

scriptsに新たに記載を追加します。

package.json
{
    "scripts": {
        "css": "postcss public/styles/tailwind.css -o public/styles/style.css"
    },
}

以下がpackage.jsonファイルの全体像です。

package.json
{
    "name": "nodejs-tailwindcss",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "css": "postcss public/styles/tailwind.css -o public/styles/style.css"
    },
    "author": "",
    "license": "ISC",
    "dependencies": {
        "autoprefixer": "^10.0.1",
        "ejs": "^3.1.5",
        "express": "^4.17.1",
        "postcss": "^8.1.6",
        "postcss-cli": "^8.2.0",
        "tailwindcss": "^1.9.6"
    }
}

それでは最後にビルドをしましょう!

ターミナル
npm run css

これでtailwind.cssの導入が完了です。

public/styles/style.cssにCSSが追加されています。

次回tailwind.cssを使ってログインページの作成を行います!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

webpack v5がリリースされた現状まとめ

プロダクションで使うのはまだ早い(11月時点

webpack v5のリリースは行われましたが、まだバグが多くありwebpackで使用するloaderやpluginは対応が全然追いついていません。

webpack v5系のIssues を眺めると多くの問題があることがわかります。

プライベートでwebpack v5にアップデートを試みたところ全部壊れました。大変危険です、webpack v5 を使用するのは 数ヶ月ほど待ったほうが良いと思います。

周辺ツールの現状

webpackを使用するにあたって特に重要な webpack-dev-server と webpack-cli の現状は以下のとおりです。

webpack-dev-server

webpack-dev-server は webpack v5対応がまだリリースされてないので、動かないケースが何点かあります。

webpack-cli

webpack v5 対応のためv4のリリースはされていますが、上記でも書いている通りwebpack-dev-serverと組み合わせるとバグります。

webpack-cli v4からwebpack-dev-server の起動をwebpack serveコマンドに統合するようになっています。

変更内容

主に下記のような変更があります。

  • 永続的なキャッシング
  • TypeScriptの対応で @types/webpack が不要になり、import { WebpackOptionsNormalized } from 'webpack'; で型を import できるようになった。(ファイル名を webpack.config.ts にする必要がある
  • Tree Shaking の最適化が入りバンドルサイズ縮小に期待できる
  • CommonJs の Tree Shaking 対応
  • css の chunk が可能になった( MiniCssExtractPlugin 使用時にできる)

破壊的変更

特に大きな破壊的変更を2つ取り上げます。

Node.js の polyfill を自動で挿入しなくなった

今まではwebpackを使用すればNode.js のコードをクライアントサイドで使用し、自動でpolyfillを挿入してくれていました。

今後 webpackはwebで動作するコードに焦点を当てていくため、Node.jsのpolyfill がバンドルに含まれ、結果的にバンドルサイズがデカくなくることを望まないようになり、
自動で polyfill を挿入しなくなりました。

polyfill を挿入したい場合は webpack/node-libs-browser を参照して、自前で挿入する必要があります。
また、クライアントサイドで Node.js に依存したパッケージを使用している場合は、パッケージの対応を待つか、フロントエンド互換のあるパッケージに変更する必要があります。

global, __filename, __dirnameもwebpackのデフォルト設定でfalseに変更されたので、使用したい場合は明示的に変更する必要があります。

デフォルトランタイムが一部 ES2015 になった

webpackの生成するコードが一部 ES2015 になったので、明示的に es5 への対応が必要となりました。

browserslistnのサポートが含まれたので、browserslistの設定またはwebpack の設定を変える、2つの選択肢があります。

  • webpack の設定

webpack.conf.js

module.exports = {
  target: ['web','es5']
};
  • browserslist の設定

.browserslistrc

last 1 version
ie >= 11
  • package.json
 "browserslist": [
    "last 1 version",
    "> 1%",
    "ie >= 11"
  ]

参考文献

webpack@5の主な変更点まとめ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

子供用の学習アプリケーションを作る(2) アニメーション編

はじめに

以前作成したアプリの続きをしていきます。
参考: 子供用の学習アプリケーションを作る(1)

今回は、コンテンツの選択画面にアニメーションを導入し、選択後の詳細画面を作成したので、その実装について記事にしていこうと思います。

動作

まずは、動作を見ていただければと思います。

test3.gif

実装

構成

構成は以下のようになっています。

❯ pwd        
/Users/yoshitaka.koitabashi/Desktop/iLearn/src/components

~/Desktop/iLearn/src/components
❯ tree .             
.
├── alsContent.tsx
├── contentsSelect.tsx
├── falcon9Content.tsx
├── header.tsx
└── spaceContent.tsx

0 directories, 5 files

今回の実装の説明に使用するのは、こちらです。
・contentsSelect.tsx
コンテンツを選択する画面

Home画面からの遷移時に、各コンテンツがふんわり浮かび上がるアニメーションを作成しました。
参考 react-native: Animated
こちらの実装なのですが、単純で、Animatedというライブラリと副作用fookであるuseEffectを利用したパターンになります。

contentsSelect.tsx
import 'react-native-gesture-handler';
import React, { useRef, useEffect } from 'react';
import {
  SafeAreaView, ScrollView, StyleSheet, Animated, TouchableOpacity,
} from 'react-native';
import { Card, Title } from 'react-native-paper';
import { createStackNavigator } from '@react-navigation/stack';
import AppHeader from './header';
import spaceContent from './spaceContent';
import alsContents from './alsContent';
import falcon9Contents from './falcon9Content';

const contents = ({ navigation }) => {
  const fadeSpace = useRef(new Animated.Value(0)).current;
  const fadeAls = useRef(new Animated.Value(0)).current;
  const fadeFalcon9 = useRef(new Animated.Value(0)).current;

  const spaceContentFadeIn = () => {
    Animated.timing(fadeSpace, {
      toValue: 1,
      duration: 500,
      useNativeDriver: true,
    }).start();
  };

  const alsContentsFadeIn = () => {
    Animated.timing(fadeAls, {
      toValue: 1,
      duration: 2000,
      useNativeDriver: true,
    }).start();
  };

  const falcon9ContentsFadeIn = () => {
    Animated.timing(fadeFalcon9, {
      toValue: 1,
      duration: 3000,
      useNativeDriver: true,
    }).start();
  };

  useEffect(() => {
    spaceContentFadeIn();
    alsContentsFadeIn();
    falcon9ContentsFadeIn();
  });

  return (
    <SafeAreaView style={styles.container}>
      <ScrollView
        contentContainerStyle={styles.contentContainer}
      >
        <TouchableOpacity
          onPress={() => {
            navigation.navigate('Home');
          }}
        >
          <AppHeader />
        </TouchableOpacity>
        <Animated.View style={[{ opacity: fadeSpace }]}>
          <Card
            onPress={() => navigation.navigate('宇宙って?')}
            style={styles.cardPadding}
          >
            <Card.Content>
              <Title style={styles.cardTitle}>宇宙って</Title>
              <Card.Cover
                source={require('../../public/img/alien.png')}
                style={styles.cardImg}
              />
            </Card.Content>
          </Card>
        </Animated.View>
        <Animated.View style={[{ opacity: fadeAls }]}>
          <Card
            onPress={() => navigation.navigate('ALSって知ってる?')}
            style={styles.cardPadding}
          >
            <Card.Content>
              <Title style={styles.cardTitle}>ALSって知ってる</Title>
              <Card.Cover
                source={require('../../public/img/health.png')}
                style={styles.cardImg}
              />
            </Card.Content>
          </Card>
        </Animated.View>
        <Animated.View style={[{ opacity: fadeFalcon9 }]}>
          <Card
            onPress={() => navigation.navigate('Falcon9がすごい')}
            style={styles.cardPadding}
          >
            <Card.Content>
              <Title style={styles.cardTitle}>Falcon 9がすごい</Title>
              <Card.Cover
                source={require('../../public/img/startup_isometric.png')}
                style={styles.cardImg}
              />
            </Card.Content>
          </Card>
        </Animated.View>
      </ScrollView>
    </SafeAreaView>
  );
};

const Stack = createStackNavigator();

const contentsSelect = () => (
  <Stack.Navigator>
    <Stack.Screen
      name="知識の森"
      component={contents}
    />
    <Stack.Screen
      name="宇宙って?"
      component={spaceContent}
    />
    <Stack.Screen
      name="ALSって知ってる?"
      component={alsContents}
    />
    <Stack.Screen
      name="Falcon9がすごい"
      component={falcon9Contents}
    />
  </Stack.Navigator>
);

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  cardImg: {
    height: 300,
  },
  cardPadding: {
    top: 60,
    marginBottom: 20,
    borderRadius: 5,
    marginLeft: 20,
    marginRight: 20,
  },
  cardTitle: {
    fontWeight: 'bold',
  },
  contentContainer: {
    paddingBottom: 50,
  },
});

export default contentsSelect;

・spaceContent.tsx
宇宙についてのコンテンツの詳細画面

詳細画面で少し面白い箇所が、下記です。
何をしているかというと、Home画面に戻す動作をしているのですが、dispatch(StackActions.popToTop())をしないと、navigationのHistoryが消されず想定外の動作をしてしまいます。

navigation.navigate('Home');
navigation.dispatch(StackActions.popToTop());
spaceContent.tsx
import * as React from 'react';
import {
  ScrollView, StyleSheet, View, Image, TouchableOpacity,
} from 'react-native';
import {
  Card, Paragraph, Chip, Avatar, Title,
} from 'react-native-paper';
import { StackActions } from '@react-navigation/native';
import { Text } from 'react-native-elements';
import AppHeader from './header';

const spaceContent = ({ navigation }) => (
  <View style={styles.container}>
    <ScrollView
      contentContainerStyle={styles.contentContainer}
    >
      <TouchableOpacity
        onPress={() => {
          navigation.navigate('Home');
          navigation.dispatch(StackActions.popToTop());
        }}
      >
        <AppHeader />
      </TouchableOpacity>
      <Card
        style={styles.cardPadding}
      >
        <Card.Content>
          <Title style={styles.cardTitle}>宇宙ってなんだろう??</Title>
          <Card.Cover
            source={require('../../public/img/alien.png')}
          />
        </Card.Content>
      </Card>
      <Card
        style={styles.cardPadding}
      >
        <Card.Content>
          <Paragraph
            style={styles.nextCardMessage}
          >
            Topics
          </Paragraph>
          <View style={styles.row}>
            <Chip style={styles.chip}>
              <Text style={styles.chipText}>宇宙開発</Text>
            </Chip>

            <Chip style={styles.chip}>
              <Text style={styles.chipText}>Jaxa</Text>
            </Chip>

            <Chip style={styles.chip}>
              <Text style={styles.chipText}>ISS</Text>
            </Chip>
          </View>
        </Card.Content>
      </Card>
      <Card
        style={styles.cardPadding}
      >
        <Card.Content>
          <Paragraph
            style={styles.nextCardMessage}
          >
            作者
          </Paragraph>
          <View style={styles.row}>
            <Avatar.Image size={70} source={require('../../public/img/space-travel.png')} />
            <Text style={styles.avatarMessage}>
              Koitabashi Yoshitaka
            </Text>
          </View>
        </Card.Content>
      </Card>
      <Card
        style={styles.cardPadding}
      >
        <Card.Content>
          <Paragraph
            style={styles.nextCardMessage}
          >
            物語
          </Paragraph>
          <Text h3 style={styles.storyTitle}>
            はじめに
          </Text>
          <Text style={styles.storyBody}>
            宇宙の誕生は約138億年前のビッグバンから始まります
          </Text>
          <Image
            source={require('../../public/img/moon2.png')}
            style={{ width: 300, height: 200 }}
          />
          <Text h4 style={styles.storyTitle}>
            ビックバンって〜?
          </Text>
          <Text style={styles.storyBody}>
            人間のまばたきよりも短い時間の中で起こった超高エネルギーの爆発ビックバンです
            ビッグバンにより小さな物質同士が結合し合い星の素となるチリやガスが生まれました
            {'\n'}
            さらにそれらの物質がくっつき合い恒星や惑星といった星々が生まれたのです
            {'\n'}
          </Text>
          <Image
            source={require('../../public/img/moon1.png')}
            style={{ width: 300, height: 200 }}
          />
          <Text style={styles.storyBody}>
            誕生以来宇宙は膨張を続けておりその膨張は加速し続けているといわれています
            {'\n'}
            そのため宇宙の大きさは現在の科学でも解明できていません
          </Text>
        </Card.Content>
      </Card>
    </ScrollView>
  </View>
);

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  backButton: {
    paddingTop: 10,
    paddingBottom: 10,
  },
  cardPadding: {
    textAlign: 'center',
    top: 60,
    marginBottom: 20,
    borderRadius: 5,
    marginLeft: 20,
    marginRight: 20,
  },
  cardTitle: {
    marginBottom: 15,
    fontSize: 20,
    fontWeight: 'bold',
  },
  cardMessage: {
    marginTop: 15,
    fontSize: 20,
    fontWeight: 'bold',
  },
  nextCardMessage: {
    marginBottom: 20,
    fontSize: 20,
    fontWeight: 'bold',
  },
  row: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    paddingHorizontal: 12,
  },
  chip: {
    backgroundColor: '#2096F3',
    margin: 2,
  },
  chipText: {
    color: '#ffffff',
  },
  avatarMessage: {
    marginLeft: 30,
    marginTop: 20,
    fontWeight: 'bold',
    textAlign: 'left',
  },
  storyTitle: {
    marginTop: 20,
    marginBottom: 20,
    fontWeight: 'bold',
  },
  storyBody: {
    marginTop: 20,
    fontWeight: 'bold',
  },
  contentContainer: {
    paddingBottom: 60,
  },
});

export default spaceContent;

おわり

・ 説明が雑になってきているので、だんだん追記していきます。w
・ 現在は、各コンテンツの内容をハードコーディングしているのですが、いずれ専用のAPIを作成するつもりなので、そこはとりあえず置いておきます。
・ あとは、Qittaのようにmarkdownで誰でも編集できるようにしていきたいと思ってます。

参考文献

宇宙について親子で楽しく学ぼう

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む