Browse Source
Created Webpack, Nodemon, and BrowserSync harness with UIkit, FontAwesome, Pretty Checkbox configured and tested.develop
16 changed files with 6045 additions and 0 deletions
@ -0,0 +1,4 @@ |
|||
.env |
|||
|
|||
node_modules |
|||
dist |
@ -0,0 +1,25 @@ |
|||
{ |
|||
"bitwise": true, |
|||
"browser": true, |
|||
"curly": true, |
|||
"eqeqeq": true, |
|||
"latedef": true, |
|||
"noarg": true, |
|||
"node": true, |
|||
"strict": "global", |
|||
"undef": true, |
|||
"unused": true, |
|||
"futurehostile": true, |
|||
"esversion": 11, |
|||
"mocha": true, |
|||
"globals": { |
|||
"markdown": true, |
|||
"moment": true, |
|||
"numeral": true, |
|||
"io": true, |
|||
"Chart": true, |
|||
"CodeMirror": true, |
|||
"UIkit": true, |
|||
"twttr": true |
|||
} |
|||
} |
@ -0,0 +1,2 @@ |
|||
DTP Chat Copyright (C) 2024 DTP Technologies, LLC |
|||
All Rights Reserved |
@ -0,0 +1,37 @@ |
|||
// home.js
|
|||
// Copyright (C) 2024 DTP Technologies, LLC
|
|||
// All Rights Reserved
|
|||
|
|||
'use strict'; |
|||
|
|||
import express from 'express'; |
|||
|
|||
export default class HomeController { |
|||
|
|||
static get isHome ( ) { return true; } |
|||
static get slug ( ) { return 'home'; } |
|||
static get className ( ) { return 'HomeController'; } |
|||
|
|||
constructor (dtp) { |
|||
this.dtp = dtp; |
|||
} |
|||
|
|||
static create (dtp) { |
|||
const instance = new HomeController(dtp); |
|||
return instance; |
|||
} |
|||
|
|||
async start ( ) { |
|||
const router = express.Router(); |
|||
this.dtp.app.use('/', router); |
|||
|
|||
router.get('/', this.getHome.bind(this)); |
|||
|
|||
return router; |
|||
} |
|||
|
|||
async getHome (req, res) { |
|||
res.locals.pageDescription = 'DTP Chat Home'; |
|||
res.render('home'); |
|||
} |
|||
} |
@ -0,0 +1,20 @@ |
|||
link(rel="apple-touch-icon" sizes="57x57" href=`/img/icon/${site.domainKey}/icon-57x57.png?v=${pkg.version}`) |
|||
link(rel="apple-touch-icon" sizes="60x60" href=`/img/icon/${site.domainKey}/icon-60x60.png?v=${pkg.version}`) |
|||
link(rel="apple-touch-icon" sizes="72x72" href=`/img/icon/${site.domainKey}/icon-72x72.png?v=${pkg.version}`) |
|||
link(rel="apple-touch-icon" sizes="76x76" href=`/img/icon/${site.domainKey}/icon-76x76.png?v=${pkg.version}`) |
|||
link(rel="apple-touch-icon" sizes="114x114" href=`/img/icon/${site.domainKey}/icon-114x114.png?v=${pkg.version}`) |
|||
link(rel="apple-touch-icon" sizes="120x120" href=`/img/icon/${site.domainKey}/icon-120x120.png?v=${pkg.version}`) |
|||
link(rel="apple-touch-icon" sizes="144x144" href=`/img/icon/${site.domainKey}/icon-144x144.png?v=${pkg.version}`) |
|||
link(rel="apple-touch-icon" sizes="152x152" href=`/img/icon/${site.domainKey}/icon-152x152.png?v=${pkg.version}`) |
|||
link(rel="apple-touch-icon" sizes="180x180" href=`/img/icon/${site.domainKey}/icon-180x180.png?v=${pkg.version}`) |
|||
link(rel="icon" type="image/png" sizes="32x32" href=`/img/icon/${site.domainKey}/icon-32x32.png?v=${pkg.version}`) |
|||
link(rel="icon" type="image/png" sizes="96x96" href=`/img/icon/${site.domainKey}/icon-96x96.png?v=${pkg.version}`) |
|||
link(rel="icon" type="image/png" sizes="16x16" href=`/img/icon/${site.domainKey}/icon-16x16.png?v=${pkg.version}`) |
|||
link(rel="icon" type="image/png" sizes="512x512" href=`/img/icon/${site.domainKey}/icon-512x512.png?v=${pkg.version}`) |
|||
link(rel="icon" type="image/png" sizes="384x384" href=`/img/icon/${site.domainKey}/icon-384x384.png?v=${pkg.version}`) |
|||
link(rel="icon" type="image/png" sizes="256x256" href=`/img/icon/${site.domainKey}/icon-512x512.png?v=${pkg.version}`) |
|||
link(rel="icon" type="image/png" sizes="192x192" href=`/img/icon/${site.domainKey}/icon-192x192.png?v=${pkg.version}`) |
|||
link(rel="manifest" href=`/manifest.json?v=${pkg.version}`) |
|||
meta(name="msapplication-TileColor" content="#f1c52f") |
|||
meta(name="msapplication-TileImage" content=`/img/icon/ms-icon-144x144.png?v=${pkg.version}`) |
|||
meta(name="theme-color" content="#f1c52f") |
@ -0,0 +1,78 @@ |
|||
block facebook-card |
|||
- |
|||
var fbCardImg = `https://${site.domain}/img/social-cards/${site.domain}.png?v=${pkg.version}`; |
|||
var fbContentType = 'website'; |
|||
var fbTitle = pageTitle || site.name; |
|||
var fbDescription = pageDescription || site.description; |
|||
var fbVideo, fbVideoWidth, fbVideoHeight; |
|||
|
|||
if ((currentView === 'dvr') && (viewName === 'home-player')) { |
|||
// use default social card assigned above |
|||
fbTitle = pageTitle; |
|||
fbDescription = pageDescription; |
|||
} else if (episode && episode.images && episode.images.thumbnail) { |
|||
if (clip && clip.images && clip.images.thumbnail) { |
|||
fbCardImg = `https://${site.domain}/image/${clip.images.thumbnail._id || clip.images.thumbnail}`; |
|||
fbTitle = clip.title; |
|||
fbDescription = clip.description; |
|||
fbContentType = 'video'; |
|||
fbVideoEmbedUrl = `https://${site.domain}/dvr/${clip.episode._id}/clip/${clip._id}/embed`; |
|||
fbVideoType = 'video/mp4'; |
|||
fbVideoWidth = 960; |
|||
fbVideoHeight = 540; |
|||
} else { |
|||
fbCardImg = `https://${site.domain}/image/${episode.images.thumbnail._id || episode.images.thumbnail}`; |
|||
fbTitle = episode.title; |
|||
fbDescription = episode.description; |
|||
} |
|||
} else if (clip && clip.images && clip.images.thumbnail) { |
|||
fbCardImg = `https://${site.domain}/image/${clip.images.thumbnail._id || clip.images.thumbnail}`; |
|||
fbTitle = clip.title; |
|||
fbDescription = clip.description; |
|||
fbContentType = 'video'; |
|||
fbVideoEmbedUrl = `https://${site.domain}/dvr/${clip.episode._id}/clip/${clip._id}/embed`; |
|||
fbVideoType = 'video/mp4'; |
|||
fbVideoWidth = 960; |
|||
fbVideoHeight = 540; |
|||
} else if (video && video.images && video.images.thumbnail) { |
|||
fbCardImg = `https://${site.domain}/image/${video.images.thumbnail._id || video.images.thumbnail}`; |
|||
fbTitle = video.title; |
|||
fbDescription = video.description; |
|||
} else if (userProfile) { |
|||
fbCardImg = getUserPictureUrl(userProfile, 'large'); |
|||
fbTitle = pageTitle; |
|||
fbDescription = pageDescription; |
|||
} else if (channel && channel.images && channel.images.thumbnail) { |
|||
fbCardImg = `https://${site.domain}/image/${channel.images.thumbnail._id || channel.images.thumbnail}`; |
|||
fbTitle = channel.name; |
|||
fbDescription = channel.description; |
|||
} else if (advertisement && advertisement.content) { |
|||
fbTitle = advertisement.content.title; |
|||
if (advertisement.content.body) { |
|||
fbDescription = marked.parse(advertisement.content.body, { renderer: fullMarkdownRenderer }).trim(); |
|||
} |
|||
switch (advertisement.content.mediaType) { |
|||
case 'Image': |
|||
fbCardImg = `https://${site.domain}/image/${advertisement.content.media._id}`; |
|||
break; |
|||
case 'Video': |
|||
if (advertisement.content && advertisement.content.media && advertisement.content.media.images && advertisement.content.media.images.thumbnail) { |
|||
fbCardImg = `https://${site.domain}/image/${advertisement.content.media.images.thumbnail._id || advertisement.content.media.images.thumbnail}`; |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
|
|||
meta(property='og:site_name', content= site.name) |
|||
meta(property='og:type', content= fbContentType) |
|||
if fbContentType === 'video' |
|||
meta(property='og:video', content= fbVideoEmbedUrl) |
|||
meta(property='og:video:type', content= fbVideoType) |
|||
meta(property='og:video:width', content= fbVideoWidth) |
|||
meta(property='og:video:height', content= fbVideoHeight) |
|||
meta(property='og:image', content= fbCardImg) |
|||
meta(property='og:image:alt', content= `${fbTitle} | ${fbDescription}`) |
|||
meta(property='og:url', content= `https://${site.domain}${dtp.request.originalUrl}`) |
|||
meta(property='og:title', content= fbTitle) |
|||
if fbDescription && (fbDescription.length > 0) |
|||
meta(property='og:description', content= fbDescription) |
@ -0,0 +1,75 @@ |
|||
block twitter-card |
|||
- |
|||
var twCardType = 'summary_large_image'; |
|||
var twCardImg = `https://${site.domain}/img/social-cards/${site.domain}.png?v=${pkg.version}`; |
|||
var twTitle = pageTitle || `${site.name} | ${site.description}`; |
|||
var twDescription = pageDescription || site.description; |
|||
var twPlayerEmbedUrl, twPlayerStreamUrl, twPlayerWidth, twPlayerHeight; |
|||
|
|||
if ((currentView === 'dvr') && (viewName === 'home-player')) { |
|||
// use default social card assigned above |
|||
twTitle = pageTitle; |
|||
twDescription = pageDescription; |
|||
} else if (episode && episode.images && episode.images.thumbnail) { |
|||
if (clip && clip.images && clip.images.thumbnail) { |
|||
twCardImg = `https://${site.domain}/image/${clip.images.thumbnail._id || clip.images.thumbnail}`; |
|||
twTitle = clip.title; |
|||
twDescription = clip.description; |
|||
twCardType = 'player'; |
|||
twPlayerEmbedUrl = `https://${site.domain}/dvr/${clip.episode._id}/clip/${clip._id}/embed`; |
|||
twPlayerStreamUrl = `https://${site.domain}/dvr/${clip.episode._id}/clip/${clip._id}/media`; |
|||
twPlayerWidth = 960; |
|||
twPlayerHeight = 540; |
|||
} else { |
|||
twCardImg = `https://${site.domain}/image/${episode.images.thumbnail._id || episode.images.thumbnail}`; |
|||
twTitle = episode.title; |
|||
twDescription = episode.description; |
|||
} |
|||
} else if (clip && clip.images && clip.images.thumbnail) { |
|||
twCardImg = `https://${site.domain}/image/${clip.images.thumbnail._id || clip.images.thumbnail}`; |
|||
twTitle = clip.title; |
|||
twDescription = clip.description; |
|||
twCardType = 'player'; |
|||
twPlayerEmbedUrl = `https://${site.domain}/dvr/${clip.episode._id}/clip/${clip._id}/embed`; |
|||
twPlayerStreamUrl = `https://${site.domain}/dvr/${clip.episode._id}/clip/${clip._id}/media`; |
|||
twPlayerWidth = 960; |
|||
twPlayerHeight = 540; |
|||
} else if (video && video.images && video.images.thumbnail) { |
|||
twCardImg = `https://${site.domain}/image/${video.images.thumbnail._id || video.images.thumbnail}`; |
|||
twTitle = video.title; |
|||
twDescription = video.description; |
|||
} else if (userProfile) { |
|||
twCardImg = getUserPictureUrl(userProfile, 'large'); |
|||
twTitle = pageTitle; |
|||
twDescription = pageDescription; |
|||
} else if (channel && channel.images && channel.images.thumbnail) { |
|||
twCardImg = `https://${site.domain}/image/${channel.images.thumbnail._id || channel.images.thumbnail}`; |
|||
twTitle = channel.name; |
|||
twDescription = channel.description; |
|||
} else if (advertisement && advertisement.content) { |
|||
twTitle = advertisement.content.title; |
|||
if (advertisement.content.body) { |
|||
twDescription = marked.parse(advertisement.content.body, { renderer: fullMarkdownRenderer }).trim(); |
|||
} |
|||
switch (advertisement.content.mediaType) { |
|||
case 'Image': |
|||
twCardImg = `https://${site.domain}/image/${advertisement.content.media._id}`; |
|||
break; |
|||
case 'Video': |
|||
if (advertisement.content && advertisement.content.media && advertisement.content.media.images && advertisement.content.media.images.thumbnail) { |
|||
twCardImg = `https://${site.domain}/image/${advertisement.content.media.images.thumbnail._id || advertisement.content.media.images.thumbnail}`; |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
|
|||
meta(name='twitter:card', content= twCardType) |
|||
meta(name='twitter:image' content= twCardImg) |
|||
meta(name='twitter:title', content= twTitle) |
|||
if twDescription && (twDescription.length > 0) |
|||
meta(name='twitter:description', content= twDescription) |
|||
if twCardType === 'player' |
|||
meta(name='twitter:player', content= twPlayerEmbedUrl) |
|||
meta(name='twitter:player:stream', content= twPlayerStreamUrl) |
|||
meta(name='twitter:player:width', content= twPlayerWidth) |
|||
meta(name='twitter:player:height', content= twPlayerHeight) |
@ -0,0 +1,13 @@ |
|||
include layout/main |
|||
block view-content |
|||
|
|||
section.uk-section.uk-section-default |
|||
.uk-container |
|||
h1= site.name |
|||
div= site.description |
|||
|
|||
p The app is doing something else. |
|||
|
|||
p |
|||
span |
|||
i.fas.fa-home |
@ -0,0 +1,84 @@ |
|||
doctype html |
|||
html(lang='en', data-obs-widget= obsWidget) |
|||
head |
|||
meta(charset='UTF-8') |
|||
meta(name='viewport', content='width=device-width, initial-scale=1.0') |
|||
meta(name='description', content= pageDescription || site.description) |
|||
|
|||
title= pageTitle ? `${pageTitle} | ${site.name}` : site.name |
|||
|
|||
meta(name="robots", content= "index,follow") |
|||
meta(name="googlebot", content= "index,follow") |
|||
meta(name="theme-color", content="#ff0013") |
|||
meta(name="apple-mobile-web-app-status-bar-style", content="black-translucent") |
|||
|
|||
block css |
|||
|
|||
link(rel='stylesheet', href=`/fontawesome/css/all.min.css?v=${pkg.version}`) |
|||
|
|||
block vendorcss |
|||
|
|||
link(rel='stylesheet', href=`/dist/chat-client.css?v=${pkg.version}`) |
|||
link(rel='stylesheet', href=`/pretty-checkbox/pretty-checkbox.min.css?v=${pkg.version}`) |
|||
|
|||
block viewcss |
|||
|
|||
block js |
|||
script(async, src=`/fontawesome/js/fontawesome.min.js?v=${pkg.version}`) |
|||
script(src=`/uikit/dist/js/uikit.min.js?v=${pkg.version}`) |
|||
script(src=`/uikit/dist/js/uikit-icons.min.js?v=${pkg.version}`) |
|||
|
|||
block pwa-support |
|||
include ../components/pwa-support |
|||
|
|||
block social-card |
|||
include ../components/social-card/twitter |
|||
include ../components/social-card/facebook |
|||
|
|||
block view-header |
|||
|
|||
script. |
|||
|
|||
function onImageLoadError (event) { |
|||
const imageType = event.currentTarget.getAttribute('data-image-type') || 'thumb'; |
|||
console.error('image error', imageType, event); |
|||
switch (imageType) { |
|||
case 'profile': |
|||
event.currentTarget.setAttribute('src', '/img/default-member.png'); |
|||
break; |
|||
case 'thumb': |
|||
event.currentTarget.setAttribute( |
|||
'src', |
|||
`/img/default-poster.${process.env.DTP_SITE_DOMAIN_KEY}.jpg`, |
|||
); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
body.dtp( |
|||
class= 'dtp-dark', |
|||
data-dtp-env= process.env.NODE_ENV, |
|||
data-dtp-domain= site.domainKey, |
|||
data-current-view= currentView, |
|||
data-is-popout= isPopOutView, |
|||
data-obs-widget= obsWidget, |
|||
data-embed-widget= embedWidget, |
|||
) |
|||
|
|||
block view-navbar |
|||
nav(uk-navbar).uk-navbar-container |
|||
.uk-navbar-left |
|||
ul.uk-navbar-nav |
|||
li.uk-active |
|||
a(href="/") |
|||
span |
|||
i.fas.fa-home |
|||
span HOME |
|||
.uk-navbar-right |
|||
ul.uk-navbar-nav |
|||
li |
|||
a(href="/welcome/sign-up") SIGN UP |
|||
li |
|||
a(href="/welcome/login") LOGIN |
|||
|
|||
block view-content |
@ -0,0 +1,5 @@ |
|||
@import "uikit/src/less/uikit.less"; |
|||
|
|||
html, body { |
|||
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; |
|||
} |
@ -0,0 +1,11 @@ |
|||
// chat-client.js
|
|||
// Copyright (C) 2024 DTP Technologies, LLC
|
|||
// All Rights Reserved
|
|||
|
|||
'use strict'; |
|||
|
|||
export class ChatApp { |
|||
constructor ( ) { |
|||
console.log('DTP app client online'); |
|||
} |
|||
} |
@ -0,0 +1,13 @@ |
|||
// config.js
|
|||
// Copyright (C) 2024 DTP Technologies, LLC
|
|||
// All Rights Reserved
|
|||
|
|||
'use strict'; |
|||
|
|||
export default { |
|||
name: process.env.DTP_SITE_NAME, |
|||
description: process.env.DTP_SITE_DESCRIPTION, |
|||
domain: process.env.DTP_SITE_DOMAIN, |
|||
domainKey: process.env.DTP_SITE_DOMAIN_KEY, |
|||
company: process.env.DTP_SITE_COMPANY || 'DTP Technologies, LLC', |
|||
}; |
@ -0,0 +1,132 @@ |
|||
// dtp-chat.js
|
|||
// Copyright (C) 2024 DTP Technologies, LLC
|
|||
// All Rights Reserved
|
|||
|
|||
'use strict'; |
|||
|
|||
import 'dotenv/config'; |
|||
|
|||
import path, { dirname } from 'path'; |
|||
import { fileURLToPath } from 'url'; |
|||
const __dirname = dirname(fileURLToPath(import.meta.url)); // jshint ignore:line
|
|||
|
|||
import { createRequire } from 'module'; |
|||
const require = createRequire(import.meta.url); // jshint ignore:line
|
|||
|
|||
import * as glob from 'glob'; |
|||
|
|||
import webpack from 'webpack'; |
|||
import webpackDevMiddleware from 'webpack-dev-middleware'; |
|||
|
|||
import WEBPACK_CONFIG from './webpack.config.js'; |
|||
|
|||
import express from 'express'; |
|||
|
|||
const APP_CONFIG = { |
|||
pkg: require('./package.json'), |
|||
}; |
|||
|
|||
class Harness { |
|||
|
|||
constructor ( ) { |
|||
this.config = { |
|||
root: __dirname, |
|||
}; |
|||
} |
|||
|
|||
async start ( ) { |
|||
this.app = express(); |
|||
|
|||
this.app.locals.config = APP_CONFIG; |
|||
this.app.locals.pkg = APP_CONFIG.pkg; // convenience
|
|||
this.app.locals.site = (await import(path.join(this.config.root, 'config', 'site.js'))).default; |
|||
|
|||
this.app.set('view engine', 'pug'); |
|||
this.app.set('views', path.join(__dirname, 'app', 'views')); |
|||
|
|||
this.app.use('/static', express.static(path.join(__dirname, 'client', 'static'))); |
|||
this.app.use('/fontawesome', express.static(path.join(__dirname, 'node_modules', '@fortawesome', 'fontawesome-free'))); |
|||
this.app.use('/uikit', express.static(path.join(__dirname, 'node_modules', 'uikit'))); |
|||
this.app.use('/pretty-checkbox', express.static(path.join(__dirname, 'node_modules', 'pretty-checkbox', 'dist'))); |
|||
|
|||
this.app.use('/dist', express.static(path.join(__dirname, 'dist'))); |
|||
|
|||
/* |
|||
* Webpack integration |
|||
*/ |
|||
if (process.env.NODE_ENV !== 'production') { |
|||
this.compiler = webpack(WEBPACK_CONFIG); |
|||
this.webpackDevMiddleware = webpackDevMiddleware(this.compiler, { |
|||
publicPath: WEBPACK_CONFIG.output.publicPath, |
|||
writeToDisk: true, |
|||
}); |
|||
this.app.use(this.webpackDevMiddleware); |
|||
} |
|||
|
|||
this.app.use((req, res, next) => { |
|||
res.locals.dtp = { |
|||
request: req, |
|||
}; |
|||
return next(); |
|||
}); |
|||
|
|||
await this.loadControllers(); |
|||
|
|||
/* |
|||
* Start the ExpressJS server |
|||
*/ |
|||
const host = process.env.DTP_HTTP_HOST || '127.0.0.1'; |
|||
const port = parseInt(process.env.DTP_HTTP_PORT || '3000', 10); |
|||
console.log('Starting application server', { host, port }); |
|||
this.app.listen(port, host, ( ) => { |
|||
console.log(`${APP_CONFIG.pkg.name} online.`); |
|||
}); |
|||
} |
|||
|
|||
async loadControllers ( ) { |
|||
const scripts = glob.sync(path.join(this.config.root, 'app', 'controllers', '*.js')); |
|||
const inits = [ ]; |
|||
|
|||
this.controllers = { }; |
|||
|
|||
for await (const script of scripts) { |
|||
try { |
|||
const file = path.parse(script); |
|||
console.log('loading controller', { name: file.base }); |
|||
|
|||
let controller = await import(script); |
|||
controller = controller.default; |
|||
controller.instance = controller.create(this); |
|||
|
|||
this.controllers[controller.slug] = controller; |
|||
inits.push(controller); |
|||
} catch (error) { |
|||
console.error('failed to load controller', { error }); |
|||
throw new Error('failed to load controller', { cause: error }); |
|||
} |
|||
} |
|||
|
|||
for await (const controller of inits) { |
|||
if (controller.isHome) { |
|||
continue; |
|||
} |
|||
await controller.instance.start(); |
|||
} |
|||
|
|||
/* |
|||
* Start the Home controller |
|||
*/ |
|||
await this.controllers.home.instance.start(); |
|||
} |
|||
} |
|||
|
|||
(async ( ) => { |
|||
|
|||
try { |
|||
const harness = new Harness(); |
|||
await harness.start(); |
|||
} catch (error) { |
|||
console.log('failed to start application harness', error); |
|||
} |
|||
|
|||
})(); |
@ -0,0 +1,51 @@ |
|||
{ |
|||
"name": "dtp-chat", |
|||
"type": "module", |
|||
"version": "0.1.0", |
|||
"description": "Next-generation realtime communications tool for the web.", |
|||
"dtpApp": { |
|||
"title": "CyberEgg 2077: Interstellar Food Fight", |
|||
"description": "In a world where memes come to life, a pineapple takes on evil and wins!" |
|||
}, |
|||
"main": "dtp-chat.js", |
|||
"scripts": { |
|||
"develop": "nodemon dtp-chat.js", |
|||
"build": "NODE_ENV=production yarn webpack --config webpack.config.js" |
|||
}, |
|||
"repository": "[email protected]:digital-telepresence/dtp-chat.git", |
|||
"author": "Rob Colbert", |
|||
"license": "LicenseRef-LICENSE", |
|||
"private": true, |
|||
"dependencies": { |
|||
"@fortawesome/fontawesome-free": "^6.5.1", |
|||
"dotenv": "^16.4.5", |
|||
"express": "^4.19.2", |
|||
"glob": "^10.3.10", |
|||
"marked": "^12.0.1", |
|||
"mongoose": "^8.2.3", |
|||
"multer": "^1.4.5-lts.1", |
|||
"numeral": "^2.0.6", |
|||
"pretty-checkbox": "^3.0.3", |
|||
"pug": "^3.0.2", |
|||
"socket.io": "^4.7.5", |
|||
"striptags": "^3.2.0" |
|||
}, |
|||
"devDependencies": { |
|||
"browser-sync": "^3.0.2", |
|||
"browser-sync-webpack-plugin": "^2.3.0", |
|||
"css-loader": "^6.10.0", |
|||
"jshint": "^2.13.6", |
|||
"less": "^4.2.0", |
|||
"less-loader": "^12.2.0", |
|||
"mini-css-extract-plugin": "^2.8.1", |
|||
"nodemon-webpack-plugin": "^4.8.2", |
|||
"style-loader": "^3.3.4", |
|||
"terser-webpack-plugin": "^5.3.10", |
|||
"uikit": "^3.19.2", |
|||
"webpack": "^5.91.0", |
|||
"webpack-cli": "^5.1.4", |
|||
"webpack-dev-middleware": "^7.1.1", |
|||
"webpack-stream": "^7.0.0", |
|||
"workbox-webpack-plugin": "^7.0.0" |
|||
} |
|||
} |
@ -0,0 +1,103 @@ |
|||
// webpack.config.js
|
|||
// Copyright (C) 2022 Rob Colbert @[email protected]
|
|||
// All Rights Reserved
|
|||
|
|||
'use strict'; |
|||
|
|||
import path, { dirname } from 'path'; |
|||
import { fileURLToPath } from 'url'; |
|||
const __dirname = dirname(fileURLToPath(import.meta.url)); // jshint ignore:line
|
|||
|
|||
import MiniCssExtractPlugin from 'mini-css-extract-plugin'; |
|||
import BrowserSyncPlugin from 'browser-sync-webpack-plugin'; |
|||
|
|||
const webpackMode = (process.env.NODE_ENV === 'production') ? 'production' : 'development'; |
|||
console.log('Webpack mode:', webpackMode); |
|||
|
|||
const plugins = [ ]; |
|||
|
|||
plugins.push(new MiniCssExtractPlugin()); |
|||
|
|||
if (webpackMode === 'development') { |
|||
plugins.push( |
|||
new BrowserSyncPlugin({ |
|||
proxy: { |
|||
target: 'http://localhost:3000', |
|||
ws: true, |
|||
}, |
|||
host: 'localhost', |
|||
open: 'local', |
|||
port: 3333, |
|||
cors: true, |
|||
ui: { |
|||
port: 3400, |
|||
}, |
|||
notify: false, |
|||
ghostMode: { |
|||
clicks: false, |
|||
forms: false, |
|||
scroll: true, |
|||
}, |
|||
logLevel: 'info', |
|||
files: [ |
|||
'./dist/*.js', |
|||
'./dist/*.css', |
|||
], |
|||
}), |
|||
); |
|||
} |
|||
|
|||
export default { |
|||
entry: { |
|||
'chat-client': [ |
|||
'./client/js/chat-client.js', |
|||
'./client/css/main.less', |
|||
], |
|||
}, |
|||
mode: webpackMode, |
|||
output: { |
|||
filename: '[name].bundle.js', |
|||
path: path.resolve(__dirname, 'dist'), |
|||
// clean: true,
|
|||
// publicPath: '/dist',
|
|||
}, |
|||
optimization: { |
|||
splitChunks: { |
|||
chunks: 'all', |
|||
}, |
|||
}, |
|||
plugins, |
|||
module: { |
|||
rules: [ |
|||
{ |
|||
test: /\.less$/i, |
|||
use: [ |
|||
{ |
|||
loader: "style-loader", |
|||
}, |
|||
{ |
|||
loader: MiniCssExtractPlugin.loader, |
|||
options: { |
|||
esModule: false, |
|||
}, |
|||
}, |
|||
{ |
|||
loader: "css-loader", |
|||
options: { |
|||
sourceMap: true, |
|||
}, |
|||
}, |
|||
{ |
|||
loader: "less-loader", |
|||
options: { |
|||
sourceMap: true, |
|||
lessOptions: { |
|||
strictMath: false, |
|||
}, |
|||
}, |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
}, |
|||
}; |
File diff suppressed because it is too large
Loading…
Reference in new issue