basic website
This commit is contained in:
parent
fc43dca665
commit
58ca081002
23 changed files with 9299 additions and 1 deletions
5
.browserslistrc
Normal file
5
.browserslistrc
Normal file
|
@ -0,0 +1,5 @@
|
|||
> 0.5%
|
||||
last 2 major versions
|
||||
Firefox ESR
|
||||
not dead
|
||||
not IE 11
|
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -573,6 +573,7 @@ FodyWeavers.xsd
|
|||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
|
@ -633,3 +634,6 @@ $RECYCLE.BIN/
|
|||
# .nfs files are created when an open file is removed but is still being accessed
|
||||
.nfs*
|
||||
|
||||
# ---> Local
|
||||
!.yarn/releases
|
||||
stats.json
|
||||
|
|
77
.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
vendored
Normal file
77
.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
vendored
Normal file
File diff suppressed because one or more lines are too long
8
.yarn/plugins/@yarnpkg/plugin-typescript.cjs
vendored
Normal file
8
.yarn/plugins/@yarnpkg/plugin-typescript.cjs
vendored
Normal file
File diff suppressed because one or more lines are too long
55
.yarn/releases/yarn-2.4.2.cjs
vendored
Executable file
55
.yarn/releases/yarn-2.4.2.cjs
vendored
Executable file
File diff suppressed because one or more lines are too long
9
.yarnrc.yml
Normal file
9
.yarnrc.yml
Normal file
|
@ -0,0 +1,9 @@
|
|||
nodeLinker: node-modules
|
||||
|
||||
plugins:
|
||||
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
|
||||
spec: "@yarnpkg/plugin-interactive-tools"
|
||||
- path: .yarn/plugins/@yarnpkg/plugin-typescript.cjs
|
||||
spec: "@yarnpkg/plugin-typescript"
|
||||
|
||||
yarnPath: .yarn/releases/yarn-2.4.2.cjs
|
11
babel.config.json
Normal file
11
babel.config.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"presets": [["@babel/preset-env", {
|
||||
"bugfixes": true,
|
||||
"spec": true,
|
||||
"useBuiltIns": "entry",
|
||||
"shippedProposals": true
|
||||
}], "@babel/preset-typescript"],
|
||||
"plugins": [["@babel/plugin-transform-runtime", {
|
||||
"corejs": 3
|
||||
}]]
|
||||
}
|
65
package.json
Normal file
65
package.json
Normal file
|
@ -0,0 +1,65 @@
|
|||
{
|
||||
"name": "website",
|
||||
"version": "0.0.1",
|
||||
"description": "Source code for my personal website",
|
||||
"main": "dist/index.js",
|
||||
"repository": "https://code.relms.dev/Relms/website",
|
||||
"author": "Daryl Ronningen <relms@relms.dev>",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"private": true,
|
||||
"sideEffects": false,
|
||||
"scripts": {
|
||||
"analyze": "webpack --config webpack.analyze.js --profile --json > stats.json && webpack-bundle-analyzer stats.json",
|
||||
"build:dev": "webpack --config webpack.dev.js",
|
||||
"build:prod": "webpack --config webpack.prod.js",
|
||||
"dev": "webpack serve --open --config webpack.dev.js",
|
||||
"prod": "serve --cors --single dist",
|
||||
"update-browserlist": "yarn browserslist --update-db",
|
||||
"update-supported-browsers": "echo \"export default $(browserslist-useragent-regexp --allowHigherVersions);\" > src/ts/supportedBrowsers.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime-corejs3": "^7.14.7",
|
||||
"bulma": "^0.9.3",
|
||||
"bulma-prefers-dark": "^0.1.0-beta.0",
|
||||
"core-js": "^3.15.1",
|
||||
"handlebars": "^4.7.7",
|
||||
"i18next": "^20.3.2",
|
||||
"i18next-browser-languagedetector": "^6.1.2",
|
||||
"i18next-chained-backend": "^3.0.2",
|
||||
"i18next-http-backend": "^1.2.6",
|
||||
"i18next-localstorage-backend": "^3.1.3",
|
||||
"regenerator-runtime": "^0.13.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.14.6",
|
||||
"@babel/plugin-transform-runtime": "^7.14.5",
|
||||
"@babel/preset-env": "^7.14.7",
|
||||
"@babel/preset-typescript": "^7.14.5",
|
||||
"@types/csp-html-webpack-plugin": "^3.0.1",
|
||||
"@types/mini-css-extract-plugin": "^1.4.3",
|
||||
"@types/regenerator-runtime": "^0.13.0",
|
||||
"@types/sass": "^1.16.0",
|
||||
"@types/webpack-bundle-analyzer": "^4.4.0",
|
||||
"babel-loader": "^8.2.2",
|
||||
"browserslist": "^4.16.6",
|
||||
"browserslist-useragent-regexp": "^3.0.0",
|
||||
"compression-webpack-plugin": "^8.0.1",
|
||||
"copy-webpack-plugin": "^9.0.1",
|
||||
"csp-html-webpack-plugin": "^5.1.0",
|
||||
"css-loader": "^5.2.6",
|
||||
"handlebars-loader": "^1.7.1",
|
||||
"html-webpack-plugin": "^5.3.2",
|
||||
"inline-source-map": "^0.6.2",
|
||||
"mini-css-extract-plugin": "^1.6.1",
|
||||
"sass": "^1.35.1",
|
||||
"sass-loader": "^12.1.0",
|
||||
"serve": "^12.0.0",
|
||||
"style-loader": "^3.0.0",
|
||||
"typescript": "^4.3.4",
|
||||
"webpack": "^5.40.0",
|
||||
"webpack-bundle-analyzer": "^4.4.2",
|
||||
"webpack-cli": "^4.7.2",
|
||||
"webpack-dev-server": "^3.11.2",
|
||||
"webpack-merge": "^5.8.0"
|
||||
}
|
||||
}
|
1
src/hbs/argonbot.hbs
Normal file
1
src/hbs/argonbot.hbs
Normal file
|
@ -0,0 +1 @@
|
|||
<h1>Lorem Ipsum</h1>
|
25
src/hbs/header.hbs
Normal file
25
src/hbs/header.hbs
Normal file
|
@ -0,0 +1,25 @@
|
|||
<nav class="navbar is-fixed-top" role="navigation" aria-label="main navigation">
|
||||
<div class="navbar-brand">
|
||||
<a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false" data-target="navbar">
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div id="navbar" class="navbar-menu">
|
||||
<div class="navbar-start">
|
||||
<a class="navbar-item" id="homeNavBar">{{i18n 'header.home'}}</a>
|
||||
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
<a class="navbar-link is-arrowless" id="currentProjectsNavBar">
|
||||
{{i18n 'header.currentProjects'}}
|
||||
</a>
|
||||
|
||||
<div class="navbar-dropdown">
|
||||
<a class="navbar-item" id="argonBotNavBar">{{i18n 'header.argonBot'}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
3
src/hbs/home.hbs
Normal file
3
src/hbs/home.hbs
Normal file
|
@ -0,0 +1,3 @@
|
|||
<div class="container">
|
||||
<h1>{{i18n 'placeholder'}}</h1>
|
||||
</div>
|
1
src/hbs/projects.hbs
Normal file
1
src/hbs/projects.hbs
Normal file
|
@ -0,0 +1 @@
|
|||
<h1>{{i18n 'placeholder'}}</h1>
|
39
src/styles/style.scss
Normal file
39
src/styles/style.scss
Normal file
|
@ -0,0 +1,39 @@
|
|||
@charset "utf-8";
|
||||
|
||||
@import '~bulma/bulma';
|
||||
@import '~bulma-prefers-dark/bulma-prefers-dark';
|
||||
|
||||
.navbar-start {
|
||||
flex-grow: 1;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media screen and (max-width: $desktop - 1px) {
|
||||
#logo{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.force-center{
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.navbar-end{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: $desktop) {
|
||||
.navbar-brand{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.navbar-end {
|
||||
padding: 20px;
|
||||
right: 0;
|
||||
position: absolute;
|
||||
}
|
||||
}
|
104
src/ts/index.ts
Normal file
104
src/ts/index.ts
Normal file
|
@ -0,0 +1,104 @@
|
|||
import 'core-js/stable';
|
||||
import 'regenerator-runtime/runtime';
|
||||
|
||||
import i18next from 'i18next';
|
||||
import HttpBackend from 'i18next-http-backend';
|
||||
import ChainedBackend from 'i18next-chained-backend';
|
||||
import LocalStorageBackend from 'i18next-localstorage-backend';
|
||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||
import Handlebars from 'handlebars/runtime';
|
||||
import supportedBrowsers from './supportedBrowsers';
|
||||
import { changeBodyData, changeState } from './utils';
|
||||
|
||||
import '../styles/style.scss';
|
||||
|
||||
const header = require("../hbs/header.hbs");
|
||||
|
||||
const jsonKeys = ['lngs', 'fallbackLng', 'ns', 'postProcess', 'interpolation'];
|
||||
|
||||
Handlebars.registerHelper('i18n', (key: any, {hash, data, fn}: any) => {
|
||||
let parsed = {};
|
||||
|
||||
jsonKeys.forEach(key => {
|
||||
if (hash[key]) {
|
||||
// @ts-ignore
|
||||
parsed[key] = JSON.parse(hash[key]);
|
||||
delete hash[key];
|
||||
}
|
||||
});
|
||||
|
||||
let options = Object.assign({}, data.i18next, hash, parsed, {returnObjects: false});
|
||||
let replace = options['replace'] = Object.assign({}, this, options['replace'], hash);
|
||||
|
||||
delete replace['i18next'];
|
||||
|
||||
if (fn) options['defaultValue'] = fn(replace);
|
||||
|
||||
return new Handlebars.SafeString(i18next.t(key, options));
|
||||
});
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async () => {
|
||||
// @ts-ignore
|
||||
await i18next.use(ChainedBackend).use(LanguageDetector).init({
|
||||
supportedLngs: ['en-US'],
|
||||
fallbackLng: 'en-US',
|
||||
backend: {
|
||||
backends: [
|
||||
LocalStorageBackend,
|
||||
HttpBackend,
|
||||
],
|
||||
backendOptions: [{
|
||||
expirationTime: 7 * 24 * 60 * 60 * 1000,
|
||||
}, {
|
||||
loadPath: '/translations/{{lng}}.json',
|
||||
}],
|
||||
},
|
||||
});
|
||||
|
||||
document.getElementsByTagName('html').item(0)!.classList.add('has-navbar-fixed-top');
|
||||
|
||||
const headerDiv = document.createElement('div');
|
||||
const bodyDiv = document.createElement('div');
|
||||
|
||||
headerDiv.innerHTML = header();
|
||||
document.body.appendChild(headerDiv);
|
||||
|
||||
const navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);
|
||||
|
||||
if (navbarBurgers.length > 0) {
|
||||
navbarBurgers.forEach(el => {
|
||||
el.addEventListener('click', () => {
|
||||
const target = el.dataset.target;
|
||||
const $target = document.getElementById(target);
|
||||
|
||||
el.classList.toggle('is-active');
|
||||
$target!.classList.toggle('is-active');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
document.getElementById('homeNavBar')!.addEventListener('click', () => {
|
||||
changeState('/');
|
||||
});
|
||||
|
||||
document.getElementById('currentProjectsNavBar')!.addEventListener('click', () => {
|
||||
changeState('/projects');
|
||||
});
|
||||
|
||||
document.getElementById('argonBotNavBar')!.addEventListener('click', () => {
|
||||
changeState('/argonBot');
|
||||
});
|
||||
|
||||
window.addEventListener('onPushState', (e) => {
|
||||
// @ts-ignore
|
||||
changeBodyData(e.detail.url, bodyDiv);
|
||||
});
|
||||
|
||||
changeBodyData(window.location.pathname, bodyDiv);
|
||||
|
||||
console.log(i18next.t('placeholder'));
|
||||
});
|
||||
|
||||
if(!supportedBrowsers.test(navigator.userAgent)) {
|
||||
alert('Your browser is not supported. The website may not work as intended.');
|
||||
}
|
1
src/ts/supportedBrowsers.ts
Normal file
1
src/ts/supportedBrowsers.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export default /((CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS)[ +]+(13[_.]0|13[_.]([1-9]|\d{2,})|13[_.]7|13[_.]([8-9]|\d{2,})|(1[4-9]|[2-9]\d|\d{3,})[_.]\d+|14[_.]0|14[_.]([1-9]|\d{2,})|14[_.]4|14[_.]([5-9]|\d{2,})|(1[5-9]|[2-9]\d|\d{3,})[_.]\d+)(?:[_.]\d+)?)|(Opera Mini(?:\/att)?\/?(\d+)?(?:\.\d+)?(?:\.\d+)?)|(Opera\/.+Opera Mobi.+Version\/(62\.0|62\.([1-9]|\d{2,})|(6[3-9]|[7-9]\d|\d{3,})\.\d+))|(Opera\/(62\.0|62\.([1-9]|\d{2,})|(6[3-9]|[7-9]\d|\d{3,})\.\d+).+Opera Mobi)|(Opera Mobi.+Opera(?:\/|\s+)(62\.0|62\.([1-9]|\d{2,})|(6[3-9]|[7-9]\d|\d{3,})\.\d+))|(SamsungBrowser\/(13\.0|13\.([1-9]|\d{2,})|(1[4-9]|[2-9]\d|\d{3,})\.\d+))|(Edge\/(90(?:\.0)?|90(?:\.([1-9]|\d{2,}))?|(9[1-9]|\d{3,})(?:\.\d+)?))|((Chromium|Chrome)\/(89\.0|89\.([1-9]|\d{2,})|(9\d|\d{3,})\.\d+)(?:\.\d+)?)|(Version\/(13\.0|13\.([1-9]|\d{2,})|(1[4-9]|[2-9]\d|\d{3,})\.\d+|14\.0|14\.([1-9]|\d{2,})|(1[5-9]|[2-9]\d|\d{3,})\.\d+)(?:\.\d+)? Safari\/)|(Firefox\/(78\.0|78\.([1-9]|\d{2,})|(79|[8-9]\d|\d{3,})\.\d+|88\.0|88\.([1-9]|\d{2,})|(89|9\d|\d{3,})\.\d+)\.\d+)|(Firefox\/(78\.0|78\.([1-9]|\d{2,})|(79|[8-9]\d|\d{3,})\.\d+|88\.0|88\.([1-9]|\d{2,})|(89|9\d|\d{3,})\.\d+)(pre|[ab]\d+[a-z]*)?)/;
|
30
src/ts/utils.ts
Normal file
30
src/ts/utils.ts
Normal file
|
@ -0,0 +1,30 @@
|
|||
const home = require('../hbs/home.hbs');
|
||||
const projects = require('../hbs/projects.hbs');
|
||||
const argonBot = require('../hbs/argonbot.hbs');
|
||||
|
||||
export const changeState = (url: string) => {
|
||||
window.history.pushState(null, '', url);
|
||||
|
||||
const event = new CustomEvent('onPushState', {detail: { url }});
|
||||
|
||||
window.dispatchEvent(event);
|
||||
}
|
||||
|
||||
export const changeBodyData = (url: string, element: HTMLDivElement) => {
|
||||
switch (url) {
|
||||
case '/':
|
||||
element.innerHTML = home();
|
||||
document.body.appendChild(element);
|
||||
break;
|
||||
case '/projects':
|
||||
element.innerHTML = projects();
|
||||
document.body.appendChild(element);
|
||||
break;
|
||||
case '/argonBot':
|
||||
element.innerHTML = argonBot();
|
||||
document.body.appendChild(element);
|
||||
break;
|
||||
default:
|
||||
changeState('/');
|
||||
}
|
||||
}
|
8
translations/en-US.json
Normal file
8
translations/en-US.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"placeholder": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n\t\taliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n\t\tDuis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur\n\t\tsint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
|
||||
"header": {
|
||||
"home": "Home",
|
||||
"currentProjects": "My Current Projects",
|
||||
"argonBot": "Argon Bot"
|
||||
}
|
||||
}
|
90
tsconfig.json
Normal file
90
tsconfig.json
Normal file
|
@ -0,0 +1,90 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"composite": true,
|
||||
"downlevelIteration": true,
|
||||
"importHelpers": true,
|
||||
"incremental": true,
|
||||
"lib": [
|
||||
"ESNext",
|
||||
"DOM"
|
||||
],
|
||||
"module": "ESNext",
|
||||
"outDir": "dist",
|
||||
"tsBuildInfoFile": "dist/.tsbuildinfo",
|
||||
"removeComments": true,
|
||||
"target": "ESNext",
|
||||
"alwaysStrict": true,
|
||||
"noImplicitAny": true,
|
||||
"noImplicitThis": true,
|
||||
"strict": true,
|
||||
"strictBindCallApply": true,
|
||||
"strictFunctionTypes": true,
|
||||
"strictNullChecks": true,
|
||||
"strictPropertyInitialization": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"esModuleInterop": true,
|
||||
"moduleResolution": "Node",
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitOverride": true,
|
||||
"noImplicitReturns": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"allowUnreachableCode": false,
|
||||
"allowUnusedLabels": false,
|
||||
"disableSizeLimit": true,
|
||||
"explainFiles": false,
|
||||
"extendedDiagnostics": false,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"importsNotUsedAsValues": "error",
|
||||
"listEmittedFiles": false,
|
||||
"listFiles": false,
|
||||
"newLine": "lf",
|
||||
"noEmitOnError": true,
|
||||
"preserveConstEnums": true,
|
||||
"resolveJsonModule": true,
|
||||
"traceResolution": false,
|
||||
"baseUrl": ".",
|
||||
"plugins": [
|
||||
{
|
||||
"name": "typescript-eslint-language-service"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"*"
|
||||
],
|
||||
"@/src": [
|
||||
"src/*"
|
||||
],
|
||||
"@lib/*": [
|
||||
"src/lib/*"
|
||||
],
|
||||
"@utils/*": [
|
||||
"src/lib/utils/*"
|
||||
],
|
||||
"@structures/*": [
|
||||
"src/lib/structures/*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"watchOptions": {
|
||||
"watchFile": "useFsEvents",
|
||||
"watchDirectory": "useFsEvents",
|
||||
"fallbackPolling": "dynamicpriority",
|
||||
"synchronousWatchDirectory": true,
|
||||
"excludeDirectories": [
|
||||
"node_modules",
|
||||
"dist"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"translations/**/*.json"
|
||||
]
|
||||
}
|
68
webpack.analyze.js
Normal file
68
webpack.analyze.js
Normal file
|
@ -0,0 +1,68 @@
|
|||
const { merge } = require("webpack-merge");
|
||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||
const CspHtmlWebpackPlugin = require('csp-html-webpack-plugin');
|
||||
const common = require('./webpack.common.js');
|
||||
|
||||
module.exports = merge(common, {
|
||||
mode: 'production',
|
||||
plugins: [
|
||||
new CspHtmlWebpackPlugin({
|
||||
'script-src': '',
|
||||
'style-src': '',
|
||||
}, {
|
||||
hashingMethod: 'sha512',
|
||||
}),
|
||||
new MiniCssExtractPlugin({
|
||||
filename: '[name].[chunkhash].css',
|
||||
}),
|
||||
],
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.[cs][ac]ss$/,
|
||||
exclude: /node_modules/,
|
||||
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
|
||||
},
|
||||
],
|
||||
},
|
||||
optimization: {
|
||||
splitChunks: {
|
||||
cacheGroups: {
|
||||
vendor: {
|
||||
test: /[\\/]node_modules[\\/]/,
|
||||
name: 'vendors',
|
||||
chunks: 'all',
|
||||
enforce: true,
|
||||
},
|
||||
js: {
|
||||
test: /\.js$/,
|
||||
name: 'js',
|
||||
chunks: 'all',
|
||||
enforce: true,
|
||||
},
|
||||
styles: {
|
||||
test: /\.css$/,
|
||||
name: 'styles',
|
||||
chunks: 'all',
|
||||
enforce: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
runtimeChunk: true,
|
||||
moduleIds: 'deterministic',
|
||||
removeAvailableModules: true,
|
||||
removeEmptyChunks: true,
|
||||
usedExports: true,
|
||||
innerGraph: true,
|
||||
concatenateModules: true,
|
||||
mergeDuplicateChunks: true,
|
||||
portableRecords: true,
|
||||
sideEffects: false,
|
||||
flagIncludedChunks: true,
|
||||
chunkIds: "deterministic",
|
||||
realContentHash: true,
|
||||
providedExports: true,
|
||||
emitOnErrors: true,
|
||||
mangleExports: "deterministic",
|
||||
},
|
||||
});
|
56
webpack.common.js
Normal file
56
webpack.common.js
Normal file
|
@ -0,0 +1,56 @@
|
|||
const path = require('path');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const CopyPlugin = require('copy-webpack-plugin');
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
index: './src/ts/index.ts',
|
||||
supportedBrowsers: './src/ts/supportedBrowsers.ts',
|
||||
utils: './src/ts/utils.ts',
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.ts$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: "babel-loader",
|
||||
options: {
|
||||
presets: ['@babel/preset-env', '@babel/preset-typescript'],
|
||||
plugins: ['@babel/plugin-transform-runtime'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.hbs$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: 'handlebars-loader',
|
||||
options: {
|
||||
knownHelpersOnly: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin(),
|
||||
new CopyPlugin({
|
||||
patterns: [
|
||||
{ from: 'translations', to: 'translations' },
|
||||
],
|
||||
}),
|
||||
],
|
||||
resolve: {
|
||||
extensions: ['.js', '.ts'],
|
||||
},
|
||||
output: {
|
||||
filename: '[name].[contenthash].js',
|
||||
chunkFilename: '[name].[contenthash].chunk.js',
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
clean: true,
|
||||
},
|
||||
experiments: {
|
||||
topLevelAwait: true,
|
||||
},
|
||||
};
|
36
webpack.dev.js
Normal file
36
webpack.dev.js
Normal file
|
@ -0,0 +1,36 @@
|
|||
const { merge } = require('webpack-merge');
|
||||
const common = require('./webpack.common.js');
|
||||
|
||||
module.exports = merge(common, {
|
||||
mode: 'development',
|
||||
devtool: 'inline-source-map',
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.[cs][ac]ss$/,
|
||||
exclude: /node_modules/,
|
||||
use: ['style-loader',
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
sourceMap: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: 'sass-loader',
|
||||
options: {
|
||||
sourceMap: true,
|
||||
},
|
||||
}],
|
||||
sideEffects: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
devServer: {
|
||||
contentBase: './dist',
|
||||
compress: true,
|
||||
liveReload: true,
|
||||
watchContentBase: true,
|
||||
historyApiFallback: true,
|
||||
},
|
||||
});
|
78
webpack.prod.js
Normal file
78
webpack.prod.js
Normal file
|
@ -0,0 +1,78 @@
|
|||
const { merge } = require("webpack-merge");
|
||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||
const CspHtmlWebpackPlugin = require('csp-html-webpack-plugin');
|
||||
const CompressionPlugin = require("compression-webpack-plugin");
|
||||
const common = require('./webpack.common.js');
|
||||
|
||||
module.exports = merge(common, {
|
||||
mode: 'production',
|
||||
plugins: [
|
||||
new CspHtmlWebpackPlugin({
|
||||
'script-src': '',
|
||||
'style-src': '',
|
||||
}, {
|
||||
hashingMethod: 'sha512',
|
||||
}),
|
||||
new MiniCssExtractPlugin({
|
||||
filename: '[name].[chunkhash].css',
|
||||
}),
|
||||
new CompressionPlugin({
|
||||
filename: "[path][base].gz",
|
||||
test: /\.(js|css|html|svg)$/,
|
||||
compressionOptions: {
|
||||
level: 9,
|
||||
},
|
||||
minRatio: Infinity,
|
||||
deleteOriginalAssets: true,
|
||||
}),
|
||||
],
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.[cs][ac]ss$/,
|
||||
exclude: /node_modules/,
|
||||
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
|
||||
},
|
||||
],
|
||||
},
|
||||
optimization: {
|
||||
splitChunks: {
|
||||
cacheGroups: {
|
||||
vendor: {
|
||||
test: /[\\/]node_modules[\\/]/,
|
||||
name: 'vendors',
|
||||
chunks: 'all',
|
||||
enforce: true,
|
||||
},
|
||||
js: {
|
||||
test: /\.js$/,
|
||||
name: 'js',
|
||||
chunks: 'all',
|
||||
enforce: true,
|
||||
},
|
||||
styles: {
|
||||
test: /\.css$/,
|
||||
name: 'styles',
|
||||
chunks: 'all',
|
||||
enforce: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
runtimeChunk: true,
|
||||
moduleIds: 'deterministic',
|
||||
removeAvailableModules: true,
|
||||
removeEmptyChunks: true,
|
||||
usedExports: true,
|
||||
innerGraph: true,
|
||||
concatenateModules: true,
|
||||
mergeDuplicateChunks: true,
|
||||
portableRecords: true,
|
||||
sideEffects: false,
|
||||
flagIncludedChunks: true,
|
||||
chunkIds: "deterministic",
|
||||
realContentHash: true,
|
||||
providedExports: true,
|
||||
emitOnErrors: true,
|
||||
mangleExports: "deterministic",
|
||||
},
|
||||
});
|
Reference in a new issue