春ですね。^ ^
なにか新しいことをはじめたくなりますね。^ ^
前回はExpressの導入を行いました。
今回は、webpackを導入します。
ゴールまでの道のり
- VPSサーバ借りる
- Ubuntu入れる
- Nginx入れる
- nodebrew、Node.js入れる
- nmp入れる
- git入れる
- Express入れる
- webpack入れる
- ES2015をES5に変換できるようにする
- PostCSSをCSSに変換できるようにする ← 前回はここまで
- Expressのディレクトリ構成変える ← 今回はここから
- pm2入れる
- サイトつくる
今回のリポジトリ
https://github.com/kimizuka/webpack-sample-expressgithub.com
前回、前々回はちょっと寄り道をして、webpackの環境を整えました。
今回は、前回、前々回の設定をExpressに取り込んでいきたいと思います。
適当なディレクトリをつくって移動
mkdir webpack-sample-express
cd webpack-sample-express
ソース用のディレクトリと書き出し用のディレクトリをつくる
mkdir _src
mkdir _src/js
mkdir _src/css
mkdir public
mkdir public/js
mkdir public/css
package.jsonをつくる
vim package.json
package.json
{ "name": "webpack-sample-express", "version": "0.0.0", "private": true, "scripts": { "start": "pm2 start ./bin/www -i max", "pm2stop": "pm2 stop all", "pm2list": "pm2 list", "build": "webpack", "watch": "webpack --watch & node ./bin/www" }, "babel": { "presets": [ "es2015", "es2017" ] }, "dependencies": { "autoprefixer": "^6.7.7", "babel-core": "^6.24.1", "babel-loader": "^6.4.1", "babel-preset-es2015": "^6.24.1", "babel-preset-es2017": "^6.24.1", "body-parser": "~1.17.1", "cookie-parser": "~1.4.3", "css-loader": "^0.28.0", "debug": "~2.6.3", "express": "~4.15.2", "extract-text-webpack-plugin": "^2.1.0", "morgan": "~1.8.1", "pm2": "^2.4.4", "postcss-extend": "^1.0.5", "postcss-for": "^2.1.1", "postcss-loader": "^1.3.3", "postcss-nested": "^1.0.0", "postcss-simple-vars": "^3.1.0", "pug": "~2.0.0-beta11", "serve-favicon": "~2.4.2", "style-loader": "^0.16.1", "webpack": "^2.3.3" } }
コンフィグファイルをつくる
vim webpack.config.babel.js
webpack.config.babel.js
import webpack from "webpack"; import ExtractTextPlugin from "extract-text-webpack-plugin"; module.exports = [{ entry: { index : __dirname + "/_src/js/index.js" }, output: { path: __dirname + "/public/js/", filename: "[name].bundle.js" }, module: { rules: [{ test: /\.js$/, exclude: [ /node_modules/ ], use: [{ loader: "babel-loader", options: { presets: [ "es2015", "es2017" ] } }], }] }, plugins: [ new webpack.optimize.UglifyJsPlugin() ] },{ entry: { index: __dirname + "/_src/css/index.css" }, output: { path: __dirname + "/public/css/", filename: "[name].bundle.css" }, module: { rules: [{ test: /\.css$/, use: ExtractTextPlugin.extract({ fallback: "style-loader", use: "css-loader?minimize!postcss-loader" }) }] }, plugins: [ new ExtractTextPlugin("[name].bundle.css") ] }];
CSSのコンフィグファイルをつくる
vim postcss.config.js
postcss.config.js
module.exports = { plugins: [ require("postcss-simple-vars")({ silent: true }), require("postcss-nested"), require("postcss-for"), require("postcss-extend"), require("autoprefixer")({ browsers: ["last 5 versions"] }) ] };
必要なモジュールをインストール
npm install
_src/js/index.jsを用意
vim _src/js/index.js
_src/js/index.js
import hello from "./hello.js"; hello.say();
_src/js/hello.jsを用意
vim _src/js/hello.js
_src/hello.js
export default class Hello { static say() { alert("HELLO."); } }
_src/css/index.cssを用意
vim _src/css/index.css
_src/css/index.css
@charset "UTF-8"; $teal: #004D40; %bg-teal { background: $teal; } body { @extend %bg-teal; display: flex; @for $i from 0 to 10 { [data-index=$i] { &:after { content: "$i"; } } } }
app.jsを用意
vim app.js
app.js
var express = require("express"); var path = require("path"); var favicon = require("serve-favicon"); var logger = require("morgan"); var cookieParser = require("cookie-parser"); var bodyParser = require("body-parser"); var index = require("./routes/index"); var app = express(); // view engine setup app.set("views", path.join(__dirname, "views")); app.set("view engine", "pug"); // uncomment after placing your favicon in /public // app.use(favicon(path.join(__dirname, "public", "favicon.ico"))); app.use(logger("dev")); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, "public"))); app.use("/", index); // catch 404 and forward to error handler app.use(function(req, res, next) { var err = new Error("Not Found"); err.status = 404; next(err); }); // error handler app.use(function(err, req, res, next) { // set locals, only providing error in development res.locals.message = err.message; res.locals.error = req.app.get("env") === "development" ? err : {}; // render the error page res.status(err.status || 500); res.render("error"); }); module.exports = app;
bin/www を作成
mkdir bin
vim bin/www
bin/www
#!/usr/bin/env node /** * Module dependencies. */ var app = require("../app"); var debug = require("debug")("app:server"); var http = require("http"); /** * Get port from environment and store in Express. */ var port = normalizePort(process.env.PORT || "3000"); app.set("port", port); /** * Create HTTP server. */ var server = http.createServer(app); /** * Listen on provided port, on all network interfaces. */ server.listen(port); server.on("error", onError); server.on("listening", onListening); /** * Normalize a port into a number, string, or false. */ function normalizePort(val) { var port = parseInt(val, 10); if (isNaN(port)) { // named pipe return val; } if (port >= 0) { // port number return port; } return false; } /** * Event listener for HTTP server "error" event. */ function onError(error) { if (error.syscall !== "listen") { throw error; } var bind = typeof port === "string" ? "Pipe " + port : "Port " + port; // handle specific listen errors with friendly messages switch (error.code) { case "EACCES": console.error(bind + " requires elevated privileges"); process.exit(1); break; case "EADDRINUSE": console.error(bind + " is already in use"); process.exit(1); break; default: throw error; } } /** * Event listener for HTTP server "listening" event. */ function onListening() { var addr = server.address(); var bind = typeof addr === "string" ? "pipe " + addr : "port " + addr.port; debug("Listening on " + bind); }
routes/index.js を作成
mkdir routes
vim routes/index.js
routes/index.js
var express = require("express"); var router = express.Router(); /* GET home page. */ router.get("/", function(req, res, next) { res.render("index", { title: "Express" }); }); module.exports = router;
view を作成
mkdir views
vim views/layout.pug
views/layout.pug
pdoctype html html head title= title link(rel='stylesheet', href='/css/index.bundle.css') body block content script(src="/js/index.bundle.js")
vim views/index.pug
views/index.pug
extends layout block content h1= title p Welcome to #{title}
vim views/error.pug
views/error.pug
extends layout block content h1= message h2= error.status pre #{error.stack}
試しにビルド!
npm run build
最終的なファイル構成
webpack-sample-express/
└ _src/
└ js/
└ hello.js
└ index.js
└ css/
└ index.css
└ app.js
└ bin/
└ www
└ nodemodules/
└ ...
└ ...
└ package.json
└ postcss.config.js
└ public/
└ js/
└ index.bundle.js
└ css/
└ index.bundle.css
└ routes
└ index.js
└ views
└ error.pug
└ index.pug
└ layout.pug
└ webpack.config.babel.js
リポジトリにプッシュ / リポジトリからプル
.sass-cache node_modules
をignoreしてリポジトリにプッシュ。
リポジトリをcloneし、
npm start
IPアドレスの3000番にアクセスすると、
てってれー。
無事にExpressが起動しています。
しかもデーモン化しているのでずーっと動きます。
リバースプロキシの設定
しかし、せっかくなので3000番ではなく80番で動かしたいところ。
そこでリバースプロキシを設定します。
sudo vim /etc/nginx/conf.d/express.conf
express.conf
server { listen 80; server_name (さくらから割り当てられているドメイン); location / { proxy_pass http://127.0.0.1:3000; } }
sudo nginx -s reload
で設定を反映。
これで、IPではなくドメインでアクセスしてみると、
てってれー。
無事にExpressが起動しています。
(IP直打ちだとNginxのデフォルト画面になりますが)
以上で長かった初期設定が終わりました。
あとは思う存分サイトをつくるだけです。