- 投稿日:2020-11-04T15:31:09+09:00
WSL、Zsh、VSCode、Docker、NodeJS セットアップまとめ in 2020
はじめに
新しいSurfaceをもらったので、せっかくだからWSLを試したいと思います。
まとめだけなので、調べる手間を省きたい方向けです。WSL、WSL2のインストール
Docker Desktop WSL 2 backendを使うためにWSL2が必要なので、最初からWSL2にアップグレードした方がいいと思います。
すでにWSL1のディストリビューションを持っている方は同じドキュメントでアップグレード方法も記載されています。
Zsh
Linux上の手順と同じ。
WSLを開き、ZSHをインストールします。
(PowerShellなどでwslを入力すれば開きます)sudo apt update sudo apt install zshoh-my-zsh & autosuggestion(自動補完)
Oh-my-zsh
sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"zsh-autosuggestion
git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestionsVimなどのテキストエディターで~/.zshrcを開き、ファイル内で以下を追加:
source ~/.zsh/zsh-autosuggestions/zsh-autosuggestions.zsh
Zshをリロード:
source ~/.zshrc
VSCode
大体VSCodeをインストールするだけで動きます。
公式マニュアル(日本語)
WSLためのExtension自分は以下の方法でDefault ShellをZSHにしたのですが、必要かどうかはわかりません:
VSCodeでCtrl+ Shift + P
→ "Select Default Shell" を入力 → WSL(ZSH)を選択NodeJS
LinuxでNodeJSをインストールのと同じ手順です。
NVMを使ってインストールします。nvm
インストール
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.36.0/install.sh | bash
以下を~/.zshrcに追加:
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvmZshをリロード:
source ~/.zshrc
NodeJS
WSLを開きます。
特定バージョンをインストールnvm install x.x.x
or 最新版
nvm install node
Docker (Docker Desktop WSL 2 backend)
要件は前述のWSL、WSL2のマニュアルに従えば満たしてるはずなので、
最新版のインストーラーをダウンロード、インストール途中でWSL2のチェックボックスを入れるだけで完成。もしWSLでdockerを入力すると以下のエラーが出てくると:
The command 'docker' could not be found in this WSL 2 distro. We recommend to activate the WSL integration in Docker Desktop settings. See https://docs.docker.com/docker-for-windows/wsl/ for details.WindowsでDocker Desktopを起動していないか、もしくは自分のLinux DistributionのWSLバージョンをチェックしてください、WSL2じゃないと動きません。
- 投稿日:2020-11-04T15:21:31+09:00
npm 最新版 インストール 方法
最新のnpmを簡単にインストールする方法伝授してゆく!!!
n packageとかいうのを使う!
sudo apt-get update sudo apt-get install nodejs sudo apt-get install npm次にキャッシュをクリアしてから、n packageを導入する
sudo npm cache clean sudo npm install n -g最新版(安定してるverとるよー)
sudo n stable パス通す sudo ln -sf /usr/local/bin/node /usr/bin/nodeこれからはn packageで管理するための最初に入れたnodeは使わないから消しておく!
sudo apt-get purge -y nodejs npmバージョン確認
npm-v node-vこのサイトにあるNode.jsのversionとnpmのバージョンが"Fermium"のやつになってれば成功!
https://nodejs.org/ja/download/releases/
- 投稿日:2020-11-04T13:36:03+09:00
JavaScript 特定桁の0と1で表すことができる全ての組み合わせを求める関数
やりたいこと
例: 引数1に
3
を渡すと3ビットで表せれるすべての組み合わせを出力する。
たまに使用するので、個人的なメモ(誰かの役に立つと嬉しい)出力例
[ [ '0', '0', '0' ], [ '0', '0', '1' ], [ '0', '1', '0' ], [ '0', '1', '1' ], [ '1', '0', '0' ], [ '1', '0', '1' ], [ '1', '1', '0' ], [ '1', '1', '1' ] ]コード
const getAllBit = (len) => { //すべての組み合わせの個数 const end = Math.pow(2, len) - 1 let result = [] for (let i = 0; i <= end; i++) { //toStringの引数に2を渡すことで2進数表記にする //len分だけ0うめ const bit = i.toString(2).padStart(len, '0') result.push(bit.split('')) } return result } console.log(getAllBit(5))追記: コメント欄でご指摘があった、再利用しない関数をなくし一つの関数でまとめました。
実行例
引数に5を渡した場合(上記のコードと同じ)
[ [ '0', '0', '0', '0', '0' ], [ '0', '0', '0', '0', '1' ], [ '0', '0', '0', '1', '0' ], [ '0', '0', '0', '1', '1' ], [ '0', '0', '1', '0', '0' ], [ '0', '0', '1', '0', '1' ], [ '0', '0', '1', '1', '0' ], [ '0', '0', '1', '1', '1' ], [ '0', '1', '0', '0', '0' ], [ '0', '1', '0', '0', '1' ], [ '0', '1', '0', '1', '0' ], [ '0', '1', '0', '1', '1' ], [ '0', '1', '1', '0', '0' ], [ '0', '1', '1', '0', '1' ], [ '0', '1', '1', '1', '0' ], [ '0', '1', '1', '1', '1' ], [ '1', '0', '0', '0', '0' ], [ '1', '0', '0', '0', '1' ], [ '1', '0', '0', '1', '0' ], [ '1', '0', '0', '1', '1' ], [ '1', '0', '1', '0', '0' ], [ '1', '0', '1', '0', '1' ], [ '1', '0', '1', '1', '0' ], [ '1', '0', '1', '1', '1' ], [ '1', '1', '0', '0', '0' ], [ '1', '1', '0', '0', '1' ], [ '1', '1', '0', '1', '0' ], [ '1', '1', '0', '1', '1' ], [ '1', '1', '1', '0', '0' ], [ '1', '1', '1', '0', '1' ], [ '1', '1', '1', '1', '0' ], [ '1', '1', '1', '1', '1' ] ]5ビットで表すことができるすべての組み合わせが出力できてます。
参考にした記事
- 投稿日:2020-11-04T09:07:43+09:00
MarkdownをGitHubに上げるだけでブログを公開できる仕組みをサクッと作ってみた
世の中には便利なCMSプロダクトがたくさんありますが、ぶっちゃけエンジニアだったらWeb上のフォームでコンテンツを入力するより、ローカルでMarkdownを作ってサクッとGitHubにPushするだけでブログ公開できたほうが楽だなーと思ったので作ってみました。
できるようになること
下記のようなインデックスページとブログページをMarkdownを作るだけで生成できるようになります。
ブログ公開の手順は下記の通りでとても簡単です。
- Markdownでブログを書く
- インデックスページを自動生成する
- GitHubにPushして自動デプロイ
実装
それでは実装していきます。
主要パッケージのバージョン
この記事を書いている時点の主要パッケージのバージョンは下記の通り。
以降は下記のパッケージが入っている前提で説明します。package.json"react": "^16.12.0", "react-dom": "^16.12.0", "react-markdown": "^4.3.1", "react-router-dom": "^5.1.2", "react-scripts": "3.4.3", "styled-components": "^5.2.0", "typescript": "^4.0.3", "@material-ui/core": "^4.9.11", "@material-ui/icons": "^4.9.1",今回の肝となっているMarkdownからwebページを生成する処理はreact-markdownを使っています。
https://github.com/rexxars/react-markdownWebサイトの準備
今回はReactを使ってWebサイトを作成します。
サイトの公開にはVercelを使っています。Vercelを使ってReactで作ったアプリケーションを公開する方法は公式ドキュメントに載っているのでそちらを参照してください。
Githubと連携してしまえばPushするだけでデプロイされるのでものすごく簡単ですよ。
https://vercel.com/guides/deploying-react-with-vercel-cra『create-react-appで作ったwebサイトからサンプルコードを漏れなく消す』という記事でWebサイトをReactで作って最低限の状態まで作る手順を書いているのでそちらも見ていただけると嬉しいです。
ブログページの構成
/blogs
でブログページへのインデックスを表示するページを作ります。
ブログページのURLは/blogs/:title
とします。:title
のところがブログごとに変動します。これに合わせてrouterを作ります。
src/pages/index.tsx// ※routerの箇所のみ抜粋しています const Blogs = lazy(() => import('./Blogs')); <Switch> <Route path="/blogs" component={Blogs} /> </Switch>src/pages/Blogs/index.tsximport React from 'react'; import { Route, Switch, Link } from 'react-router-dom'; import { List, ListItem, ListItemText } from '@material-ui/core'; import Blog from './Blog'; // data.jsonは後ほど紹介するバッチで自動生成しているjsonファイル // ブログのインデックス情報を定義しています import mds from './data.json'; export default () => { // react-markdownの機能を使ってmarkdownからページを生成 const blogs = mds.map((md) => ( <Route key={md} path={`/blogs/${md}`}> <Blog mdPath={`/mds/${md}.md`} /> </Route> )); // mdsを基にブログページへのリンクを生成 const index = mds.map((md) => ( <ListItem button component={Link} to={`/blogs/${md}`}> <ListItemText primary={md} /> </ListItem> )); return ( <Switch> {blogs} <Route> <List component="nav" aria-label="secondary mailbox folders"> {index} </List> </Route> </Switch> ); };ブログページを作成
Markdownは
public/mds/
配下に格納することにしました。
とりあえずサンプルとしてfirst.mdとsecond.mdをMarkdown形式で作りました。public/mds/first.md# first blog 初めてのブログ
public/mds/second.md# second blog 2 つめのブログ
json自動更新
public/mds/
配下のファイルを読み込み、インデックスページの情報源data.jsonを自動生成するバッチを作りました。updateBlogIndex.jsconst fs = require('fs'); fs.readdir('./public/mds/', (err, files) => { if (err) throw err; const convertedFiles = files.map((file) => ( file.replace(/\.md$/, '') )); console.log(convertedFiles); const j = JSON.stringify(convertedFiles.reverse()); console.log(j); fs.writeFileSync('./src/pages/Blogs/data.json', j); });上記を実行すると下記のようなjsonファイルがブログタイトル(ファイル名)の配列が書かれたjsonが生成されます。
src/pages/Blogs/data.json["second","first"]本番環境へデプロイ
これで実装は完了です。
かなり簡単ですよね。むしろ下手にCMS導入するより簡単です!!(もちろんCMSはもっと多機能ですがwブログ公開
最初に書いた通り下記の3つの手順でできます。
Markdownでブログを書く
public/mds/
にmarkdown形式でブログを書きます。
現在の仕様だとファイル名がタイトルになります。インデックスページを自動生成する
updateBlogIndex.js
を実行してインデックスページを生成します。GitHubにPushして自動デプロイ
Vercelを使っているのでGithubの特定のブランチにPushすると自動デプロイされます。
今後やりたいこと
とりあえずMarkdownを作るだけでブログを公開するという最低限の仕組みは作れましたが、まだCMSとしては弱すぎるので下記は実装したいと思っています。
インデックス生成バッチを手動実行するのが面倒
手動実行とはえてして忘れるものです。
CIなどで自動実行させるようにして忘れないようにするべきです。インデックスのページネーション
今は1つのページにすべてのインデックスが表示されてしまうので、ブログ数が大量に増えたら破綻します。
ページネーションさせるなどを考える必要があります。ブログの管理方法を考える
今は名前の降順にインデックスが作成されます。
ファイルの命名規則を決めて日付をいれるなどをすれば今の仕様でも管理できるかも知れませんが、別途投稿日などを持つようにして管理しやすいようにしたい。
また、public/mds/
直下に格納しているが投稿日などでディレクトリ階層を作ったほうが管理しやすくなりそう。ブログページに投稿日を入れたい
ブログはいつ投稿されたかという情報が大事なので、ブログページに投稿日を入れるようにしたい。
ブログのファイル名などに投稿日を持たせるようにして、jsonを生成するときに日付情報を持たせるようにするなど方法を検討したい。
- 投稿日:2020-11-04T01:40:58+09:00
Azure FunctionsのNodeでSQL Serverから値を取得したメモ
概要
AzureのFunctionsでNodeを利用したSQL Serverへの接続をしたメモ。
async awaitを使ってConnectionをとれるようにした。
ORMapperを自前で作ってみた。
自動でやってくれるライブラリも探せばありそうだなー。ソース
models/db.tsimport {Connection,Request, TYPES } from 'tedious' let connectionInstance = null; export const getConnection = () => new Promise<Connection>(async (resolve, reject)=>{ if(connectionInstance) { resolve(connectionInstance) } try { connectionInstance = await createConnection() resolve(connectionInstance) } catch (err) { reject(err) } }) const createConnection = ()=> new Promise<Connection>((resolve, reject)=>{ const config = { server: process.env["SQLConnectionServer"], authentication: { type: 'default', options: { userName: process.env["SQLConnectionUserName"], password: process.env["SQLConnectionUserPassword"], } }, options: { database: process.env["SQLConnectionDatabase"], rowCollectionOnDone: true, // Requestの第二引数のrowsに値を入れるために必要 rowCollectionOnRequestCompletion: true, // Requestの第二引数のrowsに値を入れるために必要 } } const connection = new Connection(config); connection.on('connect', function(err) { if (err) { reject(err) return } resolve(connection) }); }) /** * レコードをオブジェクトにして返す * @param columns レコード1行 */ const formatORMapping = <T>(columns: any[]) => { const ret = {} as T columns.forEach(col=>{ console.log(col) ret[col.metadata.colName] = col.value }) return ret } export const read = <T>(connection: Connection, query: string) => new Promise<T[]>((resolve, reject) =>{ const request = new Request(query, (err, rowCount, rows) => { if (err) { reject(err); return; } console.log(rowCount + ' row(s) returned'); resolve(rows.map<T>(formatORMapping)) }); connection.execSql(request); })models/users.tsimport * as db from './db'; interface User { UserID: number Name: string } export const select = async ()=>{ const connection = await db.getConnection(); const query = "select * from Users"; return await db.read<User[]>(connection, query) }index.tsimport { AzureFunction, Context, HttpRequest } from "@azure/functions" import * as users from './models/users'; const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> { const responseMessage = await users.select(); context.res = { body: responseMessage }; }; export default httpTrigger;参考
Azure Functions から SQLServerに接続する(node.js編)
クイック スタート:Node.js を使用して Azure SQL Database または Azure SQL Managed Instance 内のデータベースに対してクエリを実行する
Get started with SQL Server
Tedious API
Win10 + node.js から SQL Server 2019 Express に CSVファイルを書き込んでみる 修正版(tedious-connection-pool)