user profile ëģĩėĩ
webpack - babel-loader / SCSS loader / MiniCssExtractPlugin
ėēėëķí° ëĪė ęĩŽííīëģļ í í·ę°ë ļęą°ë ëĪė ëģīęģ ėķė ëķëķ ė ëĶŽ
model.findByIdAndUpdate()ë ė
ë°ėīíļ ė ė ë°ėīí°ëĨž return íëĪ.
ė
ë°ėīíļ íė ë°ėīí°ëĨž ë°ęļ° ėíīėë { new: true } ėĩė
ė ėĪėž íëĪ.
íėžė ė ëĄë íęļ° ėíīėë expressę° íėž ęē―ëĄëĨž ė ė ėëëĄ ėķę°íęģ , express.static("ëļëžė°ė ė ë ļėķėíŽ íīë ėīëĶ")ė ėŽėĐíīėž íëĪ.
app.use("/uploads", express.static("uploads"));
videoëĨž ė ëĄëí userė profileė ëęĩŽë ëģž ė ėëëĄ req.session.user._idę° ėëëž req.params.idëĨž ėŽėĐíīėž íëĪ.
// watch.pug
// ėëĩ
if String(video.owner._id) === loggedInUser._id
a(href=`${video.id}/edit`) Edit Video →
a(href=`${video.id}/delete`) Delete Video →
ė ė―ëė ęē°ęģž, ëĄę·ļėļ íė§ ėė userę° homeėė video.titleė íīëĶíī watch íėīė§ė ëĪėīę°ë Īęģ íëĐī, loggedInUserę° undefinedëžė ėëŽę° ëĻë ëŽļė ę° ë°ėíëĪ.
// middlewares.js
export const localsMiddleware = (req, res, next) => {
res.locals.siteName = "Wetube";
res.locals.loggedIn = true;
res.locals.loggedInUser = req.session.user || {}; // ėī ëķëķė || {} ëĨž ėķę°íëĪ â
};
localsMiddlewareėė userę° ëĄę·ļėļíė§ ėėë loggedInUserę° true ę°ė ę°ė§ ė ėëëĄ ėė íīėž íëĪ.
// middlewares.js
export const localsMiddleware = (req, res, next) => {
res.locals.siteName = "Wetube";
res.locals.loggedIn = Boolean(req.session.loggedIn);
res.locals.loggedInUser = req.session.user || {};
next();
};
export const protectorMiddleware = (req, res, next) => {
if (res.locals.loggedInUser) { // req.session.loggedInėžëĄ ëģęē― â
next();
} else {
return res.redirect("/login");
}
};
export const publicOnlyMiddleware = (req, res, next) => {
if (!res.locals.loggedInUser) { // req.session.loggedInėžëĄ ëģęē― â
next();
} else {
return res.redirect("/");
}
};
ėđ ėŽėīíļė ėīëĪ íėīė§ė ëĪėīę° ëë localsMiddlewareę° ėĪíëęļ° ëëŽļė req.session.userė ę°ė ë°ëž loggedInUserė ę°ėī ëŽëžė§ ėë ėė§ë§
ėė localsMiddlewareėė loggedInUserė ę°ė ëŽīėĄ°ęąī trueę° ëëëĄ || {}
ė ėķę°íęļ° ëëŽļė
ėė ę°ėī protectorMiddlewareė publicOnlyMiddlewareėė res.locals.loggedInUserëĨž ėŽėĐíëĐī ę·ļ ę°ėī ëŽīėĄ°ęąī trueę° ëėī ėëŽę° ë°ėíëĪ.
ë°ëžė, res.locals.loggedInUser ëė ė req.session.loggedIn
ė ėŽėĐíīėž íëĪ.
Webpackėīë ėë°ėĪíŽëĶ―íļë CSS, ėīëŊļė§ ëąė ëĶŽėėĪëĪė ëģííęģ ëŽķėīėĢžë ëŠĻë ëēëĪëŽ
ëĨž ë§íëĪ.
ëĪë§, react.js, vue.js ëą ëëķëķė í° íë ėėíŽėë webpackėī ėīëŊļ ëīėĨëėī ėęļ° ëëŽļė ėĪė ëĄ webpackė ė§ė ėėąíīëģž ėžė ęą°ė ėëĪ.
ę·ļëŽë, ėīë ė ęģ íėĪėžëĄėĻ ėĩėí ėīëŧęē ėëíëė§ë ėėėž íęļ° ëëŽļė ėīíīëĨž ėíī webpack configuration íėžė ėėąíīëģīë Īęģ íëĪ.
npmė ėīėĐíī webpackęģž webpack cliëĨž devDependenciesė ėĪėđíëĪ.
webpack cliëĨž ėīėĐíī ė―ėėė webpackė ëķëŽëž ė ėëĪ.
$ npm i webpack webpack-cli --save-dev
íëĄė íļ íīëė webpack.config.js
íėžė ë§ë ëĪ.
ėī íėžėë ėĩė ė―ëëĨž ėŽėĐíīėë ėëëĪ.
export default, import (x)
module.exports = {}, const ~ require() (o)
webpackė ėŽėĐíęļ° ėíīėë entryė outputė ë°ëė ė§ė íīėĪėž íëĪ.
entry
ë webpackė ęą°ėģ ëģíėíĪęģ ė íë íėžė ęē―ëĄëĨž ë§íëĪ.
output
ėīë webpackė ęą°ėģ ëģíë ęē°ęģžëŽžė ė ėĨí íėžëŠ
ęģž ę·ļ íėžėī ė ėĨë ęē―ëĄëĨž ë§íëĪ.
ėīë ę·ļ íėžėī ė ėĨë ęē―ëĄë ė ë ęē―ëĄ
ëĄ ėėąíīėž íëĪ.
ėīëĨž ėíī path.resolve(__dirname, "")
ëĨž ėīėĐíëĪ.
path.resolve()ë ė
ë Ĩí ëŠĻë ííļëĪė ëŠĻė ęē―ëĄëĄ ë§ëĪėīėĪëĪ.
dirnameėīë rootëķí° íīëęđė§ė ęē―ëĄ ė ėēīëĨž ėëŊļíëĪ.
ėĪėĩė ėíī ėëė ę°ėī ėĪė í í, src/client/js íīë ėė main.js íėžė ë§ëĪėī ėĩė ė―ëëĨž ėėąíëĪ.
// webpack.config.js
const path = require("path");
module.exports = {
entry: "./src/client/js/main.js",
output: {
filename: "main.js",
path: path.resolve(__dirname, "assets", "js"),
},
};
package.json íėžėė assets scriptëĨž ë§ë í ė―ėėė ėĪííëĪ.
// package.json
"scripts": {
"assets": "webpack --config webpack.config.js"
},
$ npm run assets
ėëėžëĄ assets/js íīëė íĻęŧ ę·ļ ėė ëģíë ė―ëę° ëīęļī main.js íėžėī ë§ëĪėīė§ ęēė íėļí ė ėëĪ.
( + assets íīëëĨž .gitignore íėžė ėķę°íėŽ githubė ė
ëĄëíė§ ėëëĄ íëĪ.)
ėī ė―ëë ė ëëĄ ėëíęģ ėė§ë§, ėžëķ ė―ëë ëļëžė°ė ę° ėīíīíė§ ëŠŧí ėë ėęļ° ëëŽļė íļíėąė íëģīíīėž íëĪ.
ë°ëžė, ėė ë°ąėë ė―ë ėēëĶŽëĨž ėíī package.json íėžėė babelė ėŽėĐíëŊėī, íëĄ íļėë ė―ë ėēëĶŽëĨž ėíī webpack.config.js íėžėė babelė ėŽėĐ
íīėž íëĪ.
íđė ėĒ
ëĨė íėžė íđė ëģíė ė ėĐ
íęļ° ėíī rulesëĨž ėŽėĐíīėž íëĪ.
webpackė loaderëĨž íĩíī íėžė ė íėíĻëĪ.
ėī ęē―ė°ėë JavaScript ė―ë(test)ëĨž babel-loader(use, loader)ëĨž ėīėĐíī ëģííīėž íëĪ.
babel-loaderė ėīėĐíęļ° ėíīėë ëĪė ëŠĻëëĪė ėĪėđíīėž íëĪ.
ëëĻļė§ë ëŠĻë ėĪėđëėī ėėžëŊëĄ babel-loaderë§ ë°ëĄ ėĪėđíīėĢžėëĪ.
npm install -D babel-loader @babel/core @babel/preset-env webpack
babel-loader ėŽėĐëēė ėëė ę°ëĪ.
babel-loaderëĨž ė°ļęģ íī webpack.config.js íėžė ėė íëĪ.
// webpack.config.js
const path = require("path");
module.exports = {
// ėëĩ
module: {
rules: [
{
test: /\.js$/,
use: {
loader: "babel-loader",
options: {
presets: [["@babel/preset-env", { targets: "defaults" }]],
},
},
},
],
},
};
ėīė webpackė babel-loaderė ëŠ ę°ė§ ėĩė ė ė íīėĢžëĐīė ėīëĨž ėīėĐíī ëŠĻë js íėžė ëģííëëĄ íëĪ.
ëĪė assets/jsėė main.js íėžė íėļíīëģīëĐī, babel-loaderė ėíī JavaScript ė―ëę° íëē ë ëģíë ęēė íėļí ė ėëĪ.
npm run assetsė ėĪííėŽ assets íīëëĨž ë§ëĪėė ëëķí° ė―ė ė°―ė mode optionėī ėĪė ëė§ ėėëĪë ęē―ęģ ëŽļęĩŽę° ë ėëĪ.
ėīëĨž íīęē°íęļ° ėíī webpackėęē ėī ė―ëę° ė§ęļ ę°ë° ėĪėļė§ ėëė§ëĨž ėë ĪėĪėž íëĪ.
modeëĨž ėĪė íė§ ėėžëĐī webpackė ęļ°ëģļė ėžëĄ production modeëĄ ėĪė ëėī ëŠĻë ė―ëëĪė ėėķíĻėžëĄėĻ ėëŽëĨž ė°ūęļ° íëĪęļ° ëëŽļėīëĪ.
ë°ëžė, íėŽë development
modeëĄ ėĪė í í, ëėĪė ėëēė ë°ąėëëĨž ė§ė ėŽëĶī ë ėīëĨž ë°ęŋëģž ęēėīëĪ.
const path = require("path");
module.exports = {
entry: "./src/client/js/main.js",
mode: "development", // ėķę° â
output: {
filename: "main.js",
path: path.resolve(__dirname, "assets", "js"),
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: "babel-loader",
options: {
presets: [["@babel/preset-env", { targets: "defaults" }]],
},
},
},
],
},
};
ėė§ expressë assetsëžë íīëė ėĄīėŽëĨž ëŠĻëĨīęģ , ëļëžė°ė ë íīëđ íīëė ė ę·ží ė ėëĪ.
server.js íėžėė express.static()
ė ėīėĐíī ëļëžė°ė ę° assets íīëė ė ę·ží ė ėëëĄ íëĪ.
ėīë ęē―ëĄė ėīëĶė ėīëĪ ėīëĶėžëĄë ėėąí ė ėė§ë§, íīë ėīëĶė ėėė ë§ë íīë ėīëĶ ę·ļëëĄ ėėąíīėž íëĪ.
ėëĨž ëĪėī, ėëė ę°ėī ėėąíëĪëĐī assets íīëė ëīėĐė /static ėĢžėëĨž íĩíī ęģĩę°íëëĄ íë ęēėīëĪ.
// server.js
app.use("/static", express.static("assets"));
base.pug íėžėī main.js íėžė ëķëŽėŽ ė ėëëĄ assets/js/main.jsëĨž base.pugė ė°ęē°íëĪ.
ëļëžė°ė ë /static ~ ęē―ëĄėė assets íīë ëīėĐė ëģž ė ėëĪ.
//- base.pug
// ėëĩ
include partials/footer
script(src="/static/js/main.js")
ėīė ėđ ėŽėīíļė ėīëĪ íėīė§ė ëĪėīę°ë main.js íėžė ëīėĐėī ėĪíëëĪ.
âŧ /static/js/main.js
ë node.js ė―ëę° ėëëž 'ëļëžė°ė ėė ėëíë js ė―ë'ėīëĪ.
ðĄ ė ëĶŽíëĐī
ð src/client/js/main.jsė ėĩė js ė―ëëĨž ėėąíëĐī
ð webpack.config.jsė ë°ëž ę·ļęēė ëģíë ęē°ęģžëŽžėī assets/js/main.jsė ëīęļ°ęē ëëĪ.
ð pug íėžė assets íīëëĄëķí° ę·ļ ęē°ęģžëŽž(js ė―ë)ė ëķëŽėĻëĪ.
client íīë ėė scss íīëëĨž ë§ë í ę·ļ ėė styles.scss íėžęģž _variables.scss íėžė ë§ë ëĪ.
// _variables.scss
$red: red;
// style.scss
@import "./_variables";
body {
background-color: $red;
}
client íīë ėė js íīë ėė main.js íėžėė, client íīë ėė scss íīë ėė styles.scss íėžė import íëĪ.
// main.js
import "../scss/styles.scss";
console.log("hi");
loaderëĨž ė§ė í ëë ėėė ėėąí ęēėēëž í ėë ėė§ë§, ėŽëŽ ę°ė loaderëĨž ëŠĻėė ė§ė í ėë ėëĪ.
ėëĨž ëĪėī, scss íėžė ėēëĶŽíęļ° ėíīėë ëĪėęģž ę°ė ėļ ę°ė loaderę° íėíëĪ.
sass-loader
: scss íėžė ėžë° css íėžëĄ ëģí$ npm install sass-loader sass webpack --save-dev
css-loader
: scss íėžė @importė url()ė import/require()ëĄ íėīė íīė$ npm install --save-dev css-loader
style-loader
: ëģíë cssëĨž ëļëžė°ė ė ė ėĐ (cssëĨž DOMė ėĢžė
)$ npm install --save-dev style-loader
ė 3ę°ė loaderëĨž ėëė ę°ėī í ëēė ëŠĻėė ė ėīėĪ ė ėëĪ.
ėīë ėĢžėí ė ė ėŽėĐ ėėė ë°ëëĄ ė ėīėž íëĪ
ë ęēėīëĪ.
ėĶ, ę°ėĨ ėēė ėŽėĐë loaderëĨž ę°ėĨ ëėĪė ė ėīėž íëĪ.
// webpack.config.js
const path = require("path");
module.exports = {
entry: "./src/client/js/main.js",
mode: "development",
output: path.resolve(__dirname, "assets", "js"),
module: {
rules: [
{
test: /\.js$/,
use: {
loader: "babel-loader",
options: {
presets: [["@babel/preset-env", { targets: "defaults" }]],
},
},
},
{
test: /\.scss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
],
},
};
ėīė ė―ėė npm run assetsëĨž ė ë ĨíëĐī
webpackė entry íėž(main.js)ė ę°ė ļėĻëĪ.
webpackė ę·ļ main.js íėžėī JavaScript íėžėė ėļėí í, ėīëĨž babelė ėīėĐíī ëģííëë°
main.js íėžėė import íīėĪ íėžėī scss íėžėė ėļėí í, scss íėžė scss, css, style loaderëĨž ėīėĐíī css íėžëĄ ëģííęģ ėīëĨž ėđ ėŽėīíļė head ėė ė
ë Ĩíī ëļëžė°ė ė ė ėĐėíĻëĪ.
CSSëĨž ėķėķíīė ëĪëĨļ íėžëĄ ëķëĶŽ
íęļ° ėíī MiniCssExtractPluginė ėĪėđíëĪ.
$ npm install --save-dev mini-css-extract-plugin
ėīë style-loaderëĨž ëė íėŽ
ëĪėęģž ę°ėī ėŽėĐí ė ėëĪ.
ė―ë ėėėīęļ° ëëŽļė ėļėļ íėë ėëĪ. ( MiniCssExtractPlugin ė°ļęģ )
// webpack.config.js
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); // ėķę° â
module.exports = {
entry: "./src/client/js/main.js",
mode: "development",
plugins: [new MiniCssExtractPlugin()], // ėķę° â
output: {
filename: "main.js",
path: path.resolve(__dirname, "assets", "js"),
},
module: {
rules: [
// ėëĩ (babel-loader)
{
test: /\.scss$/, // ëŠĻë scss íėž
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"], // ėė â
},
],
},
};
ëĪė npm run assetsëĨž ėĪííëĐī assets íīë ėė js íīë ėė main.js íėžęģž ëëķėī main.css íėžėī ėęļīëĪ.
ę·ļë°ë° jsė cssę° ëķëĶŽëęļ°ë íė§ë§, assets íīë ėė js íīëė íĻęŧ ëĪėīę° ėëĪ.
css íėžė css íīëė, js íėžė js íīëė ëĢęļ° ėíī
webpack.config.js íėžė output ëķëķėė filenameė ėė íęģ
MiniCssExtractPlugin ëķëķė filename ėĩė
ė ëĢėīėĪëĪ.
module.exports = {
entry: "./src/client/js/main.js",
mode: "development",
plugins: [
new MiniCssExtractPlugin({
filename: "css/styles.css", // ėķę° â
}),
],
output: {
filename: "js/main.js", // ėė â
path: path.resolve(__dirname, "assets"), // "js" ėė â
},
// ėëĩ
};
base.pug íėžėī style.css íėžė ëķëŽėŽ ė ėëëĄ assets/css/style.cssëĨž base.pugė ė°ęē°íëĪ.
//- base.pug
doctype html
html(lange="ko")
head
title #{pageTitle} | #{siteName}
link(rel="stylesheet" href="https://unpkg.com/mvp.css")
link(rel="stylesheet" href="/static/css/styles.css")
// ėëĩ
include partials/footer
script(src="/static/js/main.js")
ðĄ ëĪė íëē ë ė ëĶŽíëĐī
ð webpackė ėíīė client íīë ëīė íėžëĪėī ëĄëĐëëĪ.
ð webpackė ęą°ėđ íė ęē°ęģžëŽžëĪė assets íīë ėė ë§ëĪėīė§ëĪ.
ð ę·ļ ęē°ęģžëŽžëĪė base.pug íėžėė ëĄëĐëėī ëļëžė°ė ė ëģīėīęē ëëĪ.
ė§ęļėžëĄėŽ scssë íëĄ íļėë ėŠ― js íėžėė ė―ëëĨž ëģęē―í ëë§ëĪ ė―ėė npm run devëĨž ė
ë Ĩíīėžë§ ė
ë°ėīíļę° ëëĪ.
ëí ëŠ
ë đėīëĨž ėĪííęļ° ė ė íđė ëŠĻëĨž ėëŽëĨž ë°Đė§íęļ° ėíī íė assets íīëëĨž ė§ėėĪėžë§ íëĪ.
ė ėĨí ëë§ëĪ ėëėžëĄ ė
ë°ėīíļę° ëëëĄ watch
functionė ėŽėĐíëëĄ íëĪ.
output íīëę° ë§ëĪėīė§ęļ° ė ė ęļ°ėĄīė output íīëę° ėė ëëëĄ clean
ėĩė
ė ėŽėĐíëëĄ íëĪ.
// webpack.config.js
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: "./src/client/js/main.js",
mode: "development",
watch: true,
plugins: [
new MiniCssExtractPlugin({
filename: "css/style.css",
}),
],
output: {
filename: "js/main.js",
path: path.resolve(__dirname, "assets"),
clean: true,
},
module: {
rules: [
{
test: /\.js$/, // ëŠĻë js íėž
use: {
loader: "babel-loader",
options: {
presets: [["@babel/preset-env", { targets: "defaults" }]],
},
},
},
{
test: /\.scss$/, // ëŠĻë scss íėž
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
},
],
},
};
ėīė íė ë ę°ė ė―ėė íĻęŧ ęĩŽëíīėž íëĪ.
$ npm run dev
$ npm run assets
ę·ļë°ë° ėīë ęē íëĐī íëĄ íļėë ėë°ėĪíŽëĶ―íļ ė―ëëĨž ëģęē―í í ė ėĨė í ëë§ëĪ nodemonė ėíī ë°ąėëę° ėŽėėëëĪ.
ëŽļė ëĨž íīęē°íęļ° ėíī ėžëķ íėž ë° íīëë ëģęē―ëëëžë nodemonėī ėīëĨž ëŽīėíęģ ėëēëĨž ėŽėėíė§ ėëëĄ íīėž íëĪ.
ėīëĨž ėíī íëĄė íļ íīëė nodemon.json
íėžė ėėąí í ėëė ę°ėī ėėąíëĪ. (https://github.com/remy/nodemon ė°ļęģ )
// nodemon.json
{
"ignore": ["webpack.package.js", "src/client/*", "assets/*"],
"exec": "babel-node src/init.js"
}
ę·ļ í, package.json íėžėė dev script (nodemon -L --exec ...)ëĨž ėė íëĪ.
( + assets scriptë ėė íëĪ. webpack.config.json íėžė webpackėī ėĪíë ë ęļ°ëģļė ėžëĄ ė°ūë ėĪė íėžėīęļ° ëëŽļė ęĩģėī ëĪė ė ėīėĢžė§ ėėë ëëĪ. )
// ėė ė package.json
"scripts": {
"dev": "nodemon -L --exec babel-node src/init.js",
"assets": "webpack --config webpack.config.json"
}
// ėė í package.json
"scripts": {
"dev:server": "nodemon -L",
"dev:assets": "webpack"
}
script ėīëĶë ė§ęīė ėžëĄ ë°ęŋėĢžėëĪ.
íė ę°ę° ëĪëĨļ ė―ėėė ë ę°ė ëŠ
ë đėīëĨž ëŠĻë ėĪííīėž íëĪ.
íëë ėëēëĨž ėĪíėíĪęģ í
íëĶŋęģž urlė íėļíęļ° ėíī íėíęģ , ëĪëĨļ íëë client íėžė íėļíęļ° ėíī íėíëĪ.