PREV POST Nginx Config 設定
PUBLIC DATE:2021.09.09
B-09202112Nuxt.js Config 配置範例
配置 nuxt.config.js 文件前,可用 Yarn 安裝 @nuxtjs/dotenv 作為 Nuxt.js 的環境變數。
// 引用 Webpack
import webpack from 'webpack'
export default {
// // 定義 Nuxt.js 應用程序的主目錄
// srcDir: 'nuxt/',
// // yarn generate 輸出後資料夾名稱
// generate: {
// dir: 'dist'
// }
// 監聽(建置 Docker 環境時需加入)
watchers: {
webpack: {
// HMR,在生產模式下不使用(建置 Docker 環境時需加入才有作用)
poll: process.env.NODE_ENV !== 'production'
}
// webpack: {
// // 第一次 Watch 監聽的 Delay 時間
// aggregateTimeout: 300,
// // Watch 的間隔時間
// poll: 1000
// }
},
// 伺服器設定(建置 Docker 環境時需加入才有作用)
server: {
// Node.js 預設為 localhost(127.0.0.1)(process.env.NUXT_SERVER_HOST 當前環境變數設為 0.0.0.0)
host: process.env.NUXT_SERVER_HOST,
// Node.js 預設為 3000(process.env.NUXT_SERVER_PORT 環境變數不變)
port: process.env.NUXT_SERVER_PORT
},
// Server Miiddleware
serverMiddleware: [
{
path: process.env.API_PATH,
handler: '~/server/routes/frontend.js'
}, {
path: `${process.env.API_PATH}/core`,
handler: '~/server/routes/backend.js'
}
],
// // Route Miiddleware
// router: {
// middleware: ['']
// },
// Axios module configuration
axios: {
// 請求 URL 最後加入前輟
prefix: process.env.API_PATH,
// // 如單純 IP 位置,伺服器無反向代理時,取消註解,並把 proxy 改為 false 或註解與 nuxt.config.js 中的 proxy 項目改為註解或移除
// // https://axios.nuxtjs.org/options/#baseurl
// baseURL: process.env.BASE_URL,
// 開啟伺服器(Nginx)反向代理,需安裝 @nuxtjs/proxy 套件
// 注意:baseURL 與 proxy 不得同時使用。所以 proxy 在使用選項時,需要定義 prefix 而不是 baseURL,且不需要手動 nuxt.config.js 中的 modules 項目註冊 @nuxtjs/proxy
// https://axios.nuxtjs.org/options/#proxy
proxy: true
},
// 伺服器(Nginx)反向代理設定
// https://github.com/nuxt-community/proxy-module
proxy: [
process.env.BASE_URL + process.env.API_PATH
],
// Build Configuration(https://go.nuxtjs.dev/config-build)
build: {
// 解決 babel 在 Nuxt.js 的報錯。(Though the "loose" option was set to "false" in your @babel/preset-env config)當時為本機端無報錯,但上線後在 Linode VPS 運行中報錯。
babel: {
plugins: [
['@babel/plugin-proposal-private-property-in-object', {
loose: true
}]
]
},
// 關閉 Nuxt.js 加載屏(解決導致瀏覽器會持續跑loading/sse net::ERR_INCOMPLETE_CHUNKED_ENCODING 200 (OK)的錯誤)
// https://github.com/nuxt/loading-screen
loadingScreen: false,
// Webpack 加入 Plugins
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
})
],
postcss: {
plugins: {
// https://github.com/cuth/postcss-pxtorem
'postcss-pxtorem': {
// 初始 px
rootValue: 16,
// 小數點第幾位
unitPrecision: 5,
// 最小 px 值
minPixelValue: 0,
// 轉換哪些屬性('width', 'height', 'line-height'.....)
propList: ['*']
}
}
}
},
// Plugins to run before rendering page
// https://go.nuxtjs.dev/config-plugins
plugins: [
'~/plugins/axios',
{ src: '~/plugins/gtm', mode: 'client' },
{ src: '~/plugins/object-fit-images', mode: 'client' },
{ src: '~/plugins/gsap-plugins', mode: 'client' },
{ src: '~/plugins/aos', mode: 'client' }
],
// Modules for dev and build(recommended)
// https://go.nuxtjs.dev/config-modules
buildModules: [
// https://go.nuxtjs.dev/eslint
'@nuxtjs/eslint-module',
// https://github.com/nuxt-community/dotenv-module
'@nuxtjs/dotenv',
// https://github.com/nuxt-community/pwa-module
'@nuxtjs/pwa',
// https://github.com/nuxt-community/fontawesome-module
'@nuxtjs/fontawesome',
// https://github.com/pirony/nuxt-gsap
'nuxt-gsap'
],
// Modules(https://go.nuxtjs.dev/config-modules)
modules: [
// https://go.nuxtjs.dev/axios
'@nuxtjs/axios',
// https://github.com/nuxt-community/style-resources-module
'@nuxtjs/style-resources',
// https://gitlab.com/broj42/nuxt-lazy-load
['nuxt-lazy-load', {
directiveOnly: true
}],
// https://github.com/nuxt-community/auth-module
'@nuxtjs/auth-next',
// https://github.com/nuxt-community/recaptcha-module
'@nuxtjs/recaptcha',
// https://github.com/Developmint/nuxt-webfontloader
'nuxt-webfontloader'
],
// 自動導入 Components
// https://go.nuxtjs.dev/config-components
components: true,
// 自訂載入頁面 Component
loading: '~/components/Loading.vue',
// Global CSS
// https://go.nuxtjs.dev/config-css
// assets 資料夾如果要使用 SCSS,請確保已安裝 yarn add node-sass sass-loader -D
css: [
'~/assets/scss/reset_css.scss',
'~/assets/scss/app.scss'
],
// SCSS 全局變數(供其它 SCSS 文件使用)
// assets 資料夾如果要使用 SCSS 全局變數,請確保已安裝 yarn add @nuxtjs/style-resources -D
styleResources: {
scss: [
'~/assets/scss/variables.scss'
]
},
// Global page headers
// https://go.nuxtjs.dev/config-head
// 補足 PWA 所沒有提供的部分
head: {
meta: [
{ hid: 'copyright', name: 'copyright', content: `${process.env.APP_NAME}, All Rights Reserved` }
]
},
// Global page PWA
pwa: {
meta: {
// 初始值為 package.json 設定
name: process.env.APP_NAME,
short_name: process.env.APP_NAME,
description: 'Web creation, Graphic design, Visual design',
author: 'Knight Li',
// 網站語系
lang: 'zh-Hant-TW',
// Viewport
viewport: 'width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover',
// 修改網站佈景顏色
theme_color: '#161f28',
// Apple 螢幕上方狀態列顏色
appleStatusBarStyle: 'black',
// OGP
ogHost: process.env.BASE_URL,
ogImage: `${process.env.BASE_URL}/images/ogp/ogp.png`,
// Twitter Card
twitterCard: 'summary_large_image',
twitterSite: '@KnightLi_0617',
twitterCreator: '@KnightLi_0617'
},
manifest: {
// 初始值為 package.json 設定
name: process.env.APP_NAME,
short_name: process.env.APP_NAME,
description: 'Web creation, Graphic design, Visual design',
// 調整網站起始連結
start_url: '/?standalone=true',
// 網站顯示模式
display: 'standalone',
// 設定 Splash Screen 背景顏色
background_color: '#161f28',
// 修改網站佈景顏色
theme_color: '#161f28',
// 文字顯示方向,由左至右
dir: 'ltr',
// 網站語系
lang: 'zh-Hant-TW',
// 文件擴展名設置為 .json 或 .webmanifest
useWebmanifestExtension: false
}
},
// WebFont Loader
webfontloader: {
custom: {
// Google Fonts字型
families: [
'Rubik:n4,n7',
'Noto+Sans+TC:n4,n7',
'Azeret+Mono'
],
// Google Fonts 字型所對應的網址
urls: [
'https://fonts.googleapis.com/css?family=Rubik:400,700|Noto+Sans+TC:400,700|Azeret+Mono:500,700&display=swap'
]
}
},
// Fontawesome Icons
fontawesome: {
// Template component 前綴:
component: 'fa',
// Template component 後綴:
suffix: false,
// 要引入的Icons
icons: {
// 需安裝 yarn add @fortawesome/free-solid-svg-icons -D
solid: [
'faSun', 'faMoon', 'faLaptop', 'faArrowUp', 'faArrowRight', 'faArrowLeft', 'faSearch', 'faSearchPlus', 'faTag', 'faPlusCircle', 'faInfoCircle', 'faHdd', 'faCaretLeft',
'faCaretRight', 'faStepBackward', 'faStepForward', 'faAngleRight', 'faList', 'faUserLock', 'faUserCog', 'faClipboard', 'faLink', 'faUndoAlt',
'faUser', 'faPhone', 'faEnvelope', 'faQuestionCircle', 'faLock', 'faExclamationCircle', 'faCheckCircle', 'faTimesCircle', 'faKey', 'faCheckSquare',
'faPen', 'faSignOutAlt', 'faSignInAlt', 'faHome', 'faPaintBrush', 'faBook', 'faAddressBook', 'faBell', 'faUsers', 'faDatabase',
'faCog', 'faMapMarkerAlt', 'faChartLine', 'faGlobeAmericas', 'faEllipsisH', 'faSave', 'faTrash', 'faListUl', 'faFolder', 'faFileAlt', 'faFolderOpen', 'faImage',
'faDownload', 'faUserCircle'
],
// 需安裝 yarn add @fortawesome/free-regular-svg-icons -D
regular: ['faFolderOpen', 'faCalendarAlt', 'faClock', 'faEnvelope', 'faSquare', 'faWindowMaximize', 'faEye', 'faEyeSlash'],
// 需安裝 yarn add @fortawesome/free-brands-svg-icons -D
brands: ['faGithub', 'faFacebookSquare', 'faInstagram', 'faTwitter', 'faLine', 'faGoogle']
}
},
// Google reCAPTCHA 驗證
recaptcha: {
hideBadge: true,
siteKey: process.env.RECAPTCHA_SITE_KEY,
version: 3
},
// Auth 驗證
auth: {
redirect: {
login: false,
logout: false,
home: false,
callback: false
},
strategies: {
local: {
scheme: 'refresh',
token: {
// Express 輸出 JSON 格式 res.json 名稱
property: 'access_token',
// 令牌到期時間,以秒為單位
maxAge: (60 * process.env.AUTH_TOKEN_EXPIRE) || 0
},
refreshToken: {
// Express 輸出 JSON 格式 res.json 名稱
property: 'refresh_token',
// 登入後,Express 能所訪問取得 Refresh Token 的名稱
data: 'refresh_token',
// 令牌到期時間,以秒為單位
maxAge: (60 * 60 * process.env.AUTH_REFRESH_TOKEN_EXPIRE) || 0
},
user: {
// Express 輸出 JSON 格式 res.json 名稱
property: 'user',
// endpoints.user 在成功登錄後立即發送請求,獲取用戶 JSON 資料
autoFetch: true
},
endpoints: {
login: {
url: 'core/auth/login',
method: 'post'
},
refresh: {
url: 'core/auth/refresh',
method: 'post'
},
user: {
url: 'core/auth/user',
method: 'post'
},
logout: false
}
}
}
}
}
Sequelize ORM 設定
目錄、文件所在位置:
nuxt-app
┣ ─── 省略 ───
┣ server
┣ config
┗ config.js
┣ migrations
┣ models
┗ index.js
┗ seeders
┣ ─── 省略 ───
┗ .sequelizerc
.sequelizerc:
指定 Sequelize ORM 目錄文件路徑。
const path = require('path')
module.exports = {
'config': path.resolve('server/config', 'config.js'),
'migrations-path': path.resolve('server', 'migrations'),
'models-path': path.resolve('server', 'models'),
'seeders-path': path.resolve('server', 'seeders')
}
nuxt-app/server/config/config.js:
DB 環境設定文件。
// 引入 .env
require('dotenv').config()
module.exports = {
development: {
username: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
host: process.env.DB_HOST,
port: process.env.DB_PORT,
dialect: 'mariadb',
timezone: '+08:00',
logging: false,
define: {
charset: 'utf8',
dialectOptions: {
collate: 'utf8mb4_unicode_ci'
}
}
},
test: {
username: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
host: process.env.DB_HOST,
port: process.env.DB_PORT,
dialect: 'mariadb',
timezone: '+08:00',
logging: false,
define: {
charset: 'utf8',
dialectOptions: {
collate: 'utf8mb4_unicode_ci'
}
}
},
production: {
username: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
host: process.env.DB_HOST,
port: process.env.DB_PORT,
dialect: 'mariadb',
timezone: '+08:00',
logging: false,
define: {
charset: 'utf8',
dialectOptions: {
collate: 'utf8mb4_unicode_ci'
}
}
}
}
nuxt-app/server/models/index.js:
建立 DB 連線模塊。
'use strict'
// 檔案模組(Node.js 內建)
const fs = require('fs')
// 路徑設定(Node.js 內建)
const path = require('path')
// Sequelize ORM 資料庫模組
const Sequelize = require('sequelize')
// 獲取檔名
const basename = path.basename(__filename)
// 環境變量執行方式(node 或 sequelize config.js)
const env = process.env.NODE_ENV || 'development'
// sequelize DB 環境設定文件
const config = require(`${__dirname}/../config/config.js`)[env]
// 建立 DB
const db = {}
// 建立 Sequelize ORM 資料庫
let sequelize
// 資料庫連線(是否在 sequelize config.js 有使用 process.env 方式)
if (config.use_env_variable) {
// 在 config.js 裡有加入 use_env_variable 的鍵值來產生 sequelize instance
// 範例:'use_env_variable': 'mysql://DB_USER:DB_PASSWORD@DB_HOST/DB_NAME'
sequelize = new Sequelize(process.env[config.use_env_variable], config)
} else {
// 在 config.js 預設鍵值來產生 sequelize instance
sequelize = new Sequelize(config.database, config.username, config.password, config)
}
// fs 將會把相同目錄底下的 .js 以 model.name 當索引值放到 DB 物件中。執行每一個 model 的 define 資料表與 JS 對應上。
fs
.readdirSync(__dirname)
.filter((file) => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js')
})
.forEach((file) => {
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes)
db[model.name] = model
})
// 執行每一個 model 關聯的初始化與設定(static associate (models){},[modelName] 為關聯式資料庫的 foreign key 的設定與 JS 對應上)
Object.keys(db).forEach((modelName) => {
if (db[modelName].associate) {
db[modelName].associate(db)
}
})
// sequelize 全域物件與類別,加入至 DB
db.sequelize = sequelize
db.Sequelize = Sequelize
// 輸出 DB
module.exports = db
Docker 下的 Nuxt.js Config 設定
nuxt.config.js - HMR 設定:
export default {
// 監聽
watchers: {
webpack: {
// HMR,在生產模式下不使用
poll: process.env.NODE_ENV !== 'production'
}
// webpack: {
// // 第一次 Watch 監聽的 Delay 時間
// aggregateTimeout: 300,
// // Watch 的間隔時間
// poll: 1000
// }
}
}
nuxt.config.js - Host & Port 設定:
Docker Server IP【127.0.0.1】與【0.0.0.0】之差別。
更多詳細說明:說明連結
127.0.0.1 | 指【Container 容器】非指【Machine 機器】。 如果從容器綁定到 127.0.0.1 ,它將返回到同一個容器,且不接受來自外部的連接。 |
0.0.0.0 | 指【所有接口】。如果將容器綁定到特殊 0.0.0.0,容器可接受來自外部的連接。 |
export default {
server: {
// Node.js 預設為 localhost(127.0.0.1)
host: 0.0.0.0,
// Node.js 預設為 3000
port: 3000
}
}
Nuxt.js Axios Https 協議禁用證書校驗
當時在 VPS 架設上線時,Yarn 運行當中在 CMD 得到了【 unable to verify the first certificate 】的錯誤,此問題為 Axios 通信時所發生的 SSL 證書問題。
目錄、文件所在位置:
nuxt-app
┣ ─── 省略 ───
┣ plugins
┗ axios.js
┣ ─── 省略 ───
┗ nuxt.config.js
※※※※※ 注意事項 ※※※※※
這裡我是用反向代理 Proxy 方式,在 nuxt.config.js 文件中的 axios 無法 create baseURL Http 或 Https 的方式(上方有 nuxt.config.js 文件中的 axios 項目配置說明)。而是採用下方禁用證書校驗方式。
nuxt-app/plugins/axios.js:
// 引用 https
import https from 'https'
export default ({ $axios, error }) => {
// 上線佈署,Axios Https 禁用證書校驗
// https://t-kuni-tech.com/2021/04/04/nuxt-axios%E3%81%A7unable-to-verify-the-first-certificate%E3%81%8C%E7%99%BA%E7%94%9F%E3%81%97%E3%81%9F%E6%99%82%E3%81%AE%E5%AF%BE%E5%87%A6%E6%96%B9%E6%B3%95/
// https://cloud.tencent.com/developer/article/1648407
if (process.env.NODE_ENV === 'production') {
// Https 證書校驗
$axios.defaults.httpsAgent = new https.Agent({ rejectUnauthorized: false })
}
}