Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8691

expressをESモジュールに変更する手順(babel利用)

$
0
0

目的

バックエンドをESモジュールで記載できるようにしたい(フロントエンドに合わせる)という目的です。
(babelにするかtypescriptにするかで悩んでいます)

結果

  • ESMとしてexportしたモジュールはimportする、module.exportの場合(node)はrequire()を利用するということに気を付ければ、混在していても問題なく動く。

実現手段

  • expessをES6(import)で利用できるようにするため、babelでトランスパイルする。
    ⇒package.json に 「type: module」を追加すればESモジュールを使えますが、jsファイルの拡張子(.cjs、.mjs)の切り分けが面倒なのでbabelにします。

  • express-generatorでひな形を生成する。

  • 開発時は「babel-node」で実行(ビルド不要)可能とする。トランスパイルしたjsファイルが必要な場合はbuildを行う。

  • sequelizeと組み合わせて使用する(sequelizeはnodeモジュール形式で生成される。ES6形式で記載したexpress側で問題なく利用できることを確認する)

前提

  • nodeとyarnがインストール済みであること (npmを使う場合は適宜読み替えてください)

利用モジュール

{"dependencies":{"cookie-parser":"~1.4.4","debug":"~2.6.9","express":"~4.16.1","morgan":"~1.9.1"},"devDependencies":{"@babel/cli":"^7.12.10","@babel/core":"^7.12.10","@babel/node":"^7.12.10","@babel/preset-env":"^7.12.11"}}

手順

①expressのひな形をESモジュールに変更し、babelでコンパイルする

1. express-generatorでひな形を作成(viewは生成しない。.gitignoreは生成する)

npx express-generator express-generator-babel --no-view--git

2. (作成されたフォルダに移動し)必要なライブラリをインストール

yarn install

3. expressが起動することを確認

yarn start

B397.tmp.png

ブラウザで「http://localhost:3000」を表示する
515.tmp.png

4. babelインストール

yarn add @babel/cli  @babel/core @babel/preset-env -D

5. babelの設定ファイル(.babelrc)を作成する

targetにcurrentを入れることで、インストールされているnode.jsが理解できる形でトランスパイルされます。
(最近のnodeであればawaitやasyncなどがヘルパー関数ではなく、そのまま出力されます(pollyfill不要))

{"presets":[["@babel/preset-env",{"targets":{"node":"current"}}]]}

6. babelでビルドするため、フォルダ構成を変更する。

  • jsファイルを「/src」フォルダ配下にすべて移動する
mkdir src
mv  bin/ routes/ app.js src/

※「bin」「routes」フォルダと、app.jsファイルを「src」フォルダに移動している。

変更前後.png

  • フォルダ階層が変わったためソースを一部修正する

app.js (publicフォルダの位置を修正)

app.use(express.static(path.join(__dirname, 'public')));↓
app.use(express.static(path.join(__dirname, '../public')));
  • トランスパイル先フォルダを作成する
mkdir dist

7. ビルド用コマンドをpackage.jsonに追加する

package.json の "scripts"に下記コマンドを追加する。

"build":"babel src --out-dir dist --copy-files && babel ./src/bin/www --out-file ./dist/bin/www"

※.src/bin/www は拡張子がないjsファイル。フォルダ指定では対象にならないため、個別にトランスパイルをしている。

8. babelでトランスパイルを行う

yarn build

9. トランスパイルしたソースで動作確認を行う

  • package.json の "scripts"に下記コマンドを追加する。
"serve":"node ./dist/bin/www"
  • サーバを起動する
yarn serve

ブラウザで「localhost:3000」を開き、expressのトップページが開くことを確認する。
515.tmp.png

10. ESモジュールに変更して動作確認を行う

  • require()をimportに変更しても動作することを確認する。
  1. module.exportsからES6のexportに変更した場合、読み込み元も「import」に修正する必要がある。
  2. ソース内でrequire()をimportに変更しても、外部にエクスポートする「module.export」を変更しなければ、呼び出し元は変更不要。

/src/routes/index.js

// var express = require('express');  //コメントアウトimportexpressfrom'express';//追加varrouter=express.Router();/* GET home page. */router.get('/',function(req,res,next){res.render('index',{title:'Express'});});// module.exports = router;  //コメントアウトexportdefaultrouter;//追加

/src/app.js

// var express = require('express');  //コメントアウト// var path = require('path');// var cookieParser = require('cookie-parser');// var logger = require('morgan');importexpressfrom'express';//追加importpathfrom'path';importcookieParserfrom'cookie-parser';importloggerfrom'morgan';// var indexRouter = require('./routes/index');  //コメントアウトimportindexRouterfrom'./routes/index';//追加varusersRouter=require('./routes/users');varapp=express();app.use(logger('dev'));app.use(express.json());app.use(express.urlencoded({extended:false}));app.use(cookieParser());app.use(express.static(path.join(__dirname,'../public')));app.use('/',indexRouter);app.use('/users',usersRouter);module.exports=app;//コメントアウトしない。読み込み元(bin/www)を変更せず、require()のままとするため。//export default app;  // exportに書き換えると、読み込み元をimportに書き換える必要がある。

11. ESモジュール化後の動作確認

yarn build
yarn serve
  • ブラウザで「localhost:3000」を開き、expressのトップページが開くことを確認する。

12. 開発用に「babel-node」を導入する(ビルド無しで動作させるため)

  • babel-nodeをインストールする
yarn add @babel/node -D
  • package.jsonの startを修正する
"start":"node ./bin/www", ↓"start":"babel-node ./src/bin/www",
  • babel-nodeで起動することを確認する(build不要)
yarn start

ブラウザで「localhost:3000」を開き、expressのトップページが開くことを確認する。

②sequelize+sqliteを追加してデータを取得する

sequelize-cliを利用して生成したひな形(node module形式)を、express側から利用できることを確認する。

13. sequelize導入(DBはsqliteを利用する。別にサーバを作る必要がないため)

yarn add sequelize sqlite3
yarn add sequelize-cli -D
  • 初期化時に自動生成されるフォルダを「/src」配下にするため、先に「.sequelizerc」ファイルを作成する(プロジェクトルート)
touch .sequelizerc
  • sequelize関連ファイルを「/src/seqelize」で管理するように設定する(指定しない場合は、プロジェクトルートに作成される)
constpath=require('path');module.exports={'config':path.resolve('./src/sequelize/config','config.json'),'models-path':path.resolve('./src/sequelize/models'),'seeders-path':path.resolve('./src/sequelize/seeders'),'migrations-path':path.resolve('./src/sequelize/migrations'),};
  • マイグレーションのための初期化を行う
yarn sequelize init

※コマンドは、sequelize, sequelize-cli どちらでもよい(エイリアス)

プロジェクトルートではなく、/src/sequelizeに作成されます。
sequelize-init.png

  • config.jsonをsqlite用に書き換える。
{"development":{"database":"database_development","dialect":"sqlite","storage":"db/proto_app_dev.sqlite"},"test":{"database":"database_test","dialect":"sqlite","storage":"db/proto_app_test.sqlite"},"production":{"database":"database_production","dialect":"sqlite","storage":"db/proto_app.sqlite"}}

14. sequelize-cli でテーブル定義のひな形を作成後、マイグレーションを行う

  • sequelize model:generateでmodel定義と、マイグレーション用のひな形を生成する。
yarn sequelize model:generate --name User --attributes name:string,birth:date,email:string

migrationsにひな形が生成されます。
sequelize-generate.png

  • マイグレーションを行い、テーブルを作成する
yarn sequelize db:migrate

db-migrate.png

15. テスト用データを登録(db:seed)する

  • ひな形を作成する
yarn sequelize seed:generate --name user
  • ひな形を修正(登録データを用意する)
'use strict';module.exports={up:async(queryInterface,Sequelize)=>{constnow=newDate();constbirth=newDate(now);constseeds=[];constsubtractYear=(date,year)=>newDate(date.setYear(date.getFullYear()-year));seeds.push({name:"name1",birth:subtractYear(birth,1),email:"mail1@example.com",createdAt:now,updatedAt:now});seeds.push({name:"name2",birth:subtractYear(birth,1),email:"mail2@example.com",createdAt:now,updatedAt:now});seeds.push({name:"name3",birth:subtractYear(birth,1),email:"mail3@example.com",createdAt:now,updatedAt:now});returnawaitqueryInterface.bulkInsert("users",seeds,{});},down:async(queryInterface,Sequelize)=>{awaitqueryInterface.bulkDelete('users',null,{});}};
  • seedを登録する
 yarn sequelize  db:seed:all

※やり直す場合は「yarn sequelize db:seed:undo:all」

16. 作成したmodelをexpress側から利用し、登録したデータが取得できることを確認する

  • ./route/users.jsを修正し、sequelizeのmodel(users)を全レコードjson形式で返すように修正する

修正前

varexpress=require('express');varrouter=express.Router();/* GET users listing. */router.get('/',function(req,res,next){res.send('respond with a resource');});module.exports=router;

修正後

importdbfrom"../sequelize/models/index";importexpressfrom'express';constrouter=express.Router();/* GET users listing. */router.get('/',asyncfunction(req,res,next){//res.send('respond with a resource');constusers=awaitdb.User.findAll();res.json(users);});// module.exports = router;exportdefaultrouter;

呼び出し元(app.js)も変更する。

// var usersRouter = require('./routes/users');importusersRouterfrom'./routes/users';

17. ビルド後、データが取得できることを確認する

yarn build
yarn serve
  • localhost:3000/users にアクセスして、DBからデータが取得できることを確認する
[{"id":1,"name":"name1","birth":"2020-01-10T09:51:38.737Z","email":"mail1@example.com","createdAt":"2021-01-10T09:51:38.737Z","updatedAt":"2021-01-10T09:51:38.737Z"},{"id":2,"name":"name2","birth":"2019-01-10T09:51:38.737Z","email":"mail2@example.com","createdAt":"2021-01-10T09:51:38.737Z","updatedAt":"2021-01-10T09:51:38.737Z"},{"id":3,"name":"name3","birth":"2018-01-10T09:51:38.737Z","email":"mail3@example.com","createdAt":"2021-01-10T09:51:38.737Z","updatedAt":"2021-01-10T09:51:38.737Z"}]

Viewing all articles
Browse latest Browse all 8691

Trending Articles