Replace Mailchimp's 140KB JS
10
.babelrc
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"presets": [
|
||||||
|
"@babel/preset-env"
|
||||||
|
],
|
||||||
|
"plugins": [
|
||||||
|
[
|
||||||
|
"@babel/transform-runtime"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
2
.gitignore
vendored
@@ -1,5 +1,3 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
dist/
|
dist/
|
||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
public/style.css
|
|
||||||
|
|||||||
10409
package-lock.json
generated
38
package.json
@@ -2,16 +2,42 @@
|
|||||||
"name": "homepage",
|
"name": "homepage",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rm -Rf ./dist && rm -f ./public/style.css",
|
"clean": "rm -Rf dist",
|
||||||
"build": "npm run clean && postcss ./tailwind.style.css -o ./dist/style.css && cp -R ./public/* ./dist/ && cp ./dist/style.css ./public/style.css"
|
"build": "npm run clean && webpack --mode production --config webpack.config.js",
|
||||||
|
"start": "webpack-dev-server --mode development --config webpack.config.js"
|
||||||
},
|
},
|
||||||
"author": "Daniel Vassallo",
|
"author": "Daniel Vassallo",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@babel/cli": "^7.4.4",
|
||||||
|
"@babel/core": "^7.4.5",
|
||||||
|
"@babel/node": "^7.4.5",
|
||||||
|
"@babel/plugin-transform-runtime": "^7.4.4",
|
||||||
|
"@babel/preset-env": "^7.4.5",
|
||||||
"@fullhuman/postcss-purgecss": "^1.3.0",
|
"@fullhuman/postcss-purgecss": "^1.3.0",
|
||||||
"autoprefixer": "^9.6.1",
|
"autoprefixer": "^9.6.0",
|
||||||
"postcss-cli": "^6.1.3",
|
"babel-loader": "^8.0.6",
|
||||||
"tailwind": "^4.0.0",
|
"babel-polyfill": "^6.26.0",
|
||||||
"tailwindcss": "^1.1.2"
|
"css-loader": "^2.1.1",
|
||||||
|
"favicons-webpack-plugin": "^1.0.2",
|
||||||
|
"file-loader": "^3.0.1",
|
||||||
|
"html-loader": "^0.5.5",
|
||||||
|
"html-webpack-plugin": "^3.2.0",
|
||||||
|
"mini-css-extract-plugin": "^0.8.0",
|
||||||
|
"nodemon": "^1.19.1",
|
||||||
|
"npm-run-all": "^4.1.5",
|
||||||
|
"open": "6.0.0",
|
||||||
|
"opn-browser-webpack-plugin": "0.0.7",
|
||||||
|
"optimize-css-assets-webpack-plugin": "^5.0.1",
|
||||||
|
"postcss-loader": "^3.0.0",
|
||||||
|
"purgecss-webpack-plugin": "^1.6.0",
|
||||||
|
"source-map-loader": "^0.2.4",
|
||||||
|
"style-loader": "^0.23.1",
|
||||||
|
"tailwindcss": "^1.0.4",
|
||||||
|
"terser-webpack-plugin": "^1.3.0",
|
||||||
|
"url-loader": "^1.1.2",
|
||||||
|
"webpack": "^4.32.2",
|
||||||
|
"webpack-cli": "^3.3.2",
|
||||||
|
"webpack-dev-server": "^3.5.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,6 @@
|
|||||||
const purgecss = require('@fullhuman/postcss-purgecss')({
|
|
||||||
content: [
|
|
||||||
'./public/**/*.html'
|
|
||||||
],
|
|
||||||
defaultExtractor: content => content.match(/[\w-/:]+(?<!:)/g) || []
|
|
||||||
})
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: [
|
plugins: [
|
||||||
require('tailwindcss'),
|
require('tailwindcss'),
|
||||||
require('autoprefixer'),
|
require('autoprefixer')
|
||||||
purgecss
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 674 B |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 15 KiB |
@@ -1 +0,0 @@
|
|||||||
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
|
|
||||||
1
src/footer.html
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<div class="font-sans tracking-tight my-10 text-xs">Copyright © 2019 Encrypted Development LLC</div>
|
||||||
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
@@ -2,17 +2,9 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
|
<title>Userbase</title>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
|
||||||
<title>Userbase</title>
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="style.css">
|
|
||||||
|
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="img/apple-touch-icon.png">
|
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="img/favicon-32x32.png">
|
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="img/favicon-16x16.png">
|
|
||||||
<link rel="manifest" href="img/site.webmanifest">
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="pb-10">
|
<body class="pb-10">
|
||||||
@@ -22,8 +14,7 @@
|
|||||||
<img class="w-32 h-32" src="./img/icon.png">
|
<img class="w-32 h-32" src="./img/icon.png">
|
||||||
</div>
|
</div>
|
||||||
<h1 class="font-black text-6xl leading-none tracking-tight font-logo">Userbase</h1>
|
<h1 class="font-black text-6xl leading-none tracking-tight font-logo">Userbase</h1>
|
||||||
<h2 class="text-2xl leading-tight mt-1 tracking-tight">You won't believe it's not a
|
<h2 class="text-2xl leading-tight mt-1 tracking-tight">You won't believe it's not a database!</h2>
|
||||||
database!</h2>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
@@ -31,8 +22,8 @@
|
|||||||
<div class="my-10">
|
<div class="my-10">
|
||||||
<h3 class="font-black text-3xl tracking-tight" id="what-is-userbase">What is Userbase?</h3>
|
<h3 class="font-black text-3xl tracking-tight" id="what-is-userbase">What is Userbase?</h3>
|
||||||
<div class="text-left font-sans tracking-tight">
|
<div class="text-left font-sans tracking-tight">
|
||||||
<p class="mb-4">Userbase is like a database, but purpose-built for web app user data. It's accessible
|
<p class="mb-4">Userbase is like a database, but purpose-built for web app user data. It's accessible directly
|
||||||
directly from the browser through a very simple JavaScript SDK.</p>
|
from the browser through a very simple JavaScript SDK.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -41,22 +32,19 @@
|
|||||||
<div class="my-10">
|
<div class="my-10">
|
||||||
<h3 class="font-black text-3xl tracking-tight" id="why-not-a-database">Why isn't it a database?</h3>
|
<h3 class="font-black text-3xl tracking-tight" id="why-not-a-database">Why isn't it a database?</h3>
|
||||||
<div class="text-left font-sans tracking-tight">
|
<div class="text-left font-sans tracking-tight">
|
||||||
<p class="mb-4">With Userbase you can durably store, update, delete, and query user data. But that's where
|
<p class="mb-4">With Userbase you can durably store, update, delete, and query user data. But that's where the
|
||||||
the similarities with traditional databases end.</p>
|
similarities with traditional databases end.</p>
|
||||||
<h4 class="font-bold text-xl tracking-tight" id="zero-management">Zero management</h4>
|
<h4 class="font-bold text-xl tracking-tight" id="zero-management">Zero management</h4>
|
||||||
<p class="mb-4">Unlike a real database, all Userbase
|
<p class="mb-4">Unlike a real database, all Userbase queries run in the browser, with the server-side acting as
|
||||||
queries run in the browser, with the server-side acting as a dumb data store. There's no database to manage
|
a dumb data store. There's no database to manage and worry about.
|
||||||
and worry about.
|
|
||||||
</p>
|
</p>
|
||||||
<h4 class="font-bold text-xl tracking-tight" id="user-management">Built-in user management</h4>
|
<h4 class="font-bold text-xl tracking-tight" id="user-management">Built-in user management</h4>
|
||||||
<p class="mb-4">Unlike a real database, Userbase takes care of your user accounts. It comes with built-in
|
<p class="mb-4">Unlike a real database, Userbase takes care of your user accounts. It comes with built-in APIs
|
||||||
APIs for user signups, logins, and access control.</p>
|
for user signups, logins, and access control.</p>
|
||||||
<h4 class="font-bold text-xl tracking-tight" id="e2ee">End-to-end encrypted</h4>
|
<h4 class="font-bold text-xl tracking-tight" id="e2ee">End-to-end encrypted</h4>
|
||||||
<p class="mb-4">Unlike a real database, Userbase won't show you what your users store in your web
|
<p class="mb-4">Unlike a real database, Userbase won't show you what your users store in your web app.</p>
|
||||||
app.</p>
|
|
||||||
<p class="mb-4"></p>Wait, what!? — Yes, that's a feature — maybe the most important feature. Userbase spares you
|
<p class="mb-4"></p>Wait, what!? — Yes, that's a feature — maybe the most important feature. Userbase spares you
|
||||||
from
|
from the liability of handling user data by encrypting everything in the browser, using keys that always stay
|
||||||
the liability of handling user data by encrypting everything in the browser, using keys that always stay
|
|
||||||
with the user.</p>
|
with the user.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -88,8 +76,8 @@
|
|||||||
<h4 class="font-bold text-xl tracking-tight" id="oss">Open source</h4>
|
<h4 class="font-bold text-xl tracking-tight" id="oss">Open source</h4>
|
||||||
<p class="mb-4">Userbase is being developed in the open, and is <a
|
<p class="mb-4">Userbase is being developed in the open, and is <a
|
||||||
href="https://github.com/encrypted-dev/userbase" target="_blank" rel="noopener noreferrer">100%
|
href="https://github.com/encrypted-dev/userbase" target="_blank" rel="noopener noreferrer">100%
|
||||||
open-source</a>, MIT licensed. You can modify
|
open-source</a>, MIT licensed. You can modify and extend the backend to your liking, and run it yourself in
|
||||||
and extend the backend to your liking, and run it yourself in your AWS account, always under your control.</p>
|
your AWS account, always under your control.</p>
|
||||||
|
|
||||||
<h4 class="font-bold text-xl tracking-tight" id="saas">As a service</h4>
|
<h4 class="font-bold text-xl tracking-tight" id="saas">As a service</h4>
|
||||||
<p class="mb-4">Or for just $39/month you can go fully serverless, backendless, databaseless, and AWSless!</p>
|
<p class="mb-4">Or for just $39/month you can go fully serverless, backendless, databaseless, and AWSless!</p>
|
||||||
@@ -105,32 +93,24 @@
|
|||||||
<p class="mb-4">Enter your email to receive occasional updates about Userbase. No spam ever.</p>
|
<p class="mb-4">Enter your email to receive occasional updates about Userbase. No spam ever.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="mc_embed_signup">
|
|
||||||
<form
|
<form
|
||||||
action="https://danielvassallo.us20.list-manage.com/subscribe/post?u=e3b0fd293a0e6d7ea0080fafe&id=d0aae9dd3e"
|
action="https://danielvassallo.us20.list-manage.com/subscribe/post?u=e3b0fd293a0e6d7ea0080fafe&id=d0aae9dd3e"
|
||||||
method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate"
|
method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate"
|
||||||
target="_blank" novalidate>
|
target="_blank">
|
||||||
<div id="mc_embed_signup_scroll">
|
|
||||||
<div class="mc-field-group">
|
<div class="mc-field-group">
|
||||||
<input type="email" value="" name="EMAIL" id="mce-EMAIL" placeholder="Email address"
|
<input type="email" value="" name="EMAIL" id="mce-EMAIL" required autocorrect="off" spellcheck="false"
|
||||||
|
placeholder="Email address"
|
||||||
class="font-light text-sm h-10 p-2 border border-gray-500 outline-none w-64 rounded font-mono my-4 inline-block">
|
class="font-light text-sm h-10 p-2 border border-gray-500 outline-none w-64 rounded font-mono my-4 inline-block">
|
||||||
|
|
||||||
<input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe"
|
<input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe"
|
||||||
class="rounded-lg w-40 h-10 bg-yellowish font-bold cursor-pointer text-gray-900 inline-block relative"
|
class="rounded-lg w-40 h-10 bg-yellowish font-bold cursor-pointer text-gray-900 inline-block relative"
|
||||||
style="top: 1px;">
|
style="top: 1px;">
|
||||||
</div>
|
</div>
|
||||||
<div id="mce-responses" class="clear">
|
<div class="mc-status" class="hidden"></div>
|
||||||
<div class="response" id="mce-error-response" style="display:none"></div>
|
<div style="position: absolute; left: -5000px;" aria-hidden="true">
|
||||||
<div class="response" id="mce-success-response" style="display:none"></div>
|
<input type="text" name="b_e3b0fd293a0e6d7ea0080fafe_d0aae9dd3e" tabindex="-1" value=""></div>
|
||||||
</div>
|
|
||||||
<div style="position: absolute; left: -5000px;" aria-hidden="true"><input type="text"
|
|
||||||
name="b_e3b0fd293a0e6d7ea0080fafe_d0aae9dd3e" tabindex="-1" value=""></div>
|
|
||||||
<div class="clear"></div>
|
<div class="clear"></div>
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--End mc_embed_signup-->
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -141,10 +121,8 @@
|
|||||||
<div class="text-left font-sans tracking-tight">
|
<div class="text-left font-sans tracking-tight">
|
||||||
<p class="mb-4">This product is the work of <a href="https://twitter.com/dvassallo" target="_blank"
|
<p class="mb-4">This product is the work of <a href="https://twitter.com/dvassallo" target="_blank"
|
||||||
rel="noopener noreferrer">Daniel Vassallo</a> and <a href="https://twitter.com/justinberman95"
|
rel="noopener noreferrer">Daniel Vassallo</a> and <a href="https://twitter.com/justinberman95"
|
||||||
target="_blank" rel="noopener noreferrer">Justin Berman</a>.
|
target="_blank" rel="noopener noreferrer">Justin Berman</a>. We're a small independent business, structured
|
||||||
We're a small independent business, structured to be lean, profitable, and sustainable. We're here for the
|
to be lean, profitable, and sustainable. We're here for the long haul.
|
||||||
long
|
|
||||||
haul.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class="mb-4">If you have any questions, or there's anything we can do to help you with your web app, please
|
<p class="mb-4">If you have any questions, or there's anything we can do to help you with your web app, please
|
||||||
@@ -154,16 +132,10 @@
|
|||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<div class="font-sans tracking-tight my-10 text-xs">
|
${require('./footer.html')}
|
||||||
Copyright © 2019 Encrypted Development LLC
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type='text/javascript' src='mc-validate.js'></script>
|
|
||||||
<script type='text/javascript'>
|
|
||||||
(function ($) { window.fnames = new Array(); window.ftypes = new Array(); fnames[0] = 'EMAIL'; ftypes[0] = 'email'; fnames[1] = 'FNAME'; ftypes[1] = 'text'; fnames[2] = 'LNAME'; ftypes[2] = 'text'; fnames[3] = 'ADDRESS'; ftypes[3] = 'address'; fnames[4] = 'PHONE'; ftypes[4] = 'phone'; fnames[5] = 'BIRTHDAY'; ftypes[5] = 'birthday'; }(jQuery)); var $mcj = jQuery.noConflict(true);
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
67
src/index.js
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import './style.css'
|
||||||
|
|
||||||
|
var serialize = function (form) {
|
||||||
|
var serialized = ''
|
||||||
|
|
||||||
|
for (var i = 0; i < form.elements.length; i++) {
|
||||||
|
|
||||||
|
var field = form.elements[i]
|
||||||
|
|
||||||
|
if (!field.name || field.disabled || field.type === 'file' || field.type === 'reset' || field.type === 'submit' || field.type === 'button') continue
|
||||||
|
|
||||||
|
if ((field.type !== 'checkbox' && field.type !== 'radio') || field.checked) {
|
||||||
|
serialized += '&' + encodeURIComponent(field.name) + "=" + encodeURIComponent(field.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return serialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.displayMailChimpStatus = function (data) {
|
||||||
|
if (!data.result || !data.msg) return
|
||||||
|
|
||||||
|
var mcStatus = document.querySelector('.mc-status')
|
||||||
|
|
||||||
|
if (!mcStatus) return
|
||||||
|
|
||||||
|
mcStatus.innerHTML = data.msg
|
||||||
|
|
||||||
|
//mcStatus.addAttribute('tabindex', '-1')
|
||||||
|
mcStatus.focus()
|
||||||
|
|
||||||
|
mcStatus.classList.remove('hidden')
|
||||||
|
|
||||||
|
if (data.result === 'error') {
|
||||||
|
mcStatus.classList.remove('mc-success')
|
||||||
|
mcStatus.classList.add('mc-error')
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mcStatus.classList.remove('mc-error');
|
||||||
|
mcStatus.classList.add('mc-success')
|
||||||
|
}
|
||||||
|
|
||||||
|
var submitMailChimpForm = function (form) {
|
||||||
|
var url = form.getAttribute('action')
|
||||||
|
url = url.replace('/post?u=', '/post-json?u=')
|
||||||
|
url += serialize(form) + '&c=displayMailChimpStatus'
|
||||||
|
|
||||||
|
var script = window.document.createElement('script')
|
||||||
|
script.src = url
|
||||||
|
|
||||||
|
var ref = window.document.getElementsByTagName('script')[0]
|
||||||
|
ref.parentNode.insertBefore(script, ref)
|
||||||
|
|
||||||
|
script.onload = function () {
|
||||||
|
this.remove()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('submit', function (event) {
|
||||||
|
if (!event.target.classList.contains('validate')) return
|
||||||
|
|
||||||
|
event.preventDefault()
|
||||||
|
|
||||||
|
submitMailChimpForm(event.target)
|
||||||
|
|
||||||
|
}, false)
|
||||||
@@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
|
|
||||||
@tailwind utilities;
|
|
||||||
|
|
||||||
a {
|
a {
|
||||||
@apply underline;
|
@apply underline;
|
||||||
}
|
}
|
||||||
@@ -11,3 +9,17 @@ a {
|
|||||||
a:hover {
|
a:hover {
|
||||||
@apply text-orange-700;
|
@apply text-orange-700;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mc-status:focus {
|
||||||
|
@apply outline-none
|
||||||
|
}
|
||||||
|
|
||||||
|
.mc-success {
|
||||||
|
@apply text-green-600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mc-error {
|
||||||
|
@apply text-red-600;
|
||||||
|
}
|
||||||
|
|
||||||
|
@tailwind utilities;
|
||||||
124
webpack.config.js
Executable file
@@ -0,0 +1,124 @@
|
|||||||
|
const path = require('path')
|
||||||
|
const glob = require('glob')
|
||||||
|
const webpack = require('webpack')
|
||||||
|
const TerserPlugin = require('terser-webpack-plugin')
|
||||||
|
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
|
||||||
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
||||||
|
const PurgecssPlugin = require('purgecss-webpack-plugin')
|
||||||
|
const HtmlWebPackPlugin = require('html-webpack-plugin')
|
||||||
|
const FaviconsWebpackPlugin = require('favicons-webpack-plugin')
|
||||||
|
const OpenBrowserPlugin = require('opn-browser-webpack-plugin')
|
||||||
|
|
||||||
|
module.exports = (env, argv) => {
|
||||||
|
|
||||||
|
const PATHS = {
|
||||||
|
src: path.join(__dirname, 'src')
|
||||||
|
}
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
entry: {
|
||||||
|
main: './src/index.js'
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
path: path.join(__dirname, 'dist'),
|
||||||
|
publicPath: '/',
|
||||||
|
filename: '[name].js',
|
||||||
|
globalObject: 'this'
|
||||||
|
},
|
||||||
|
target: 'web',
|
||||||
|
devtool: 'source-map',
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.js', '.jsx'],
|
||||||
|
},
|
||||||
|
performance: {
|
||||||
|
hints: false
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.css$/,
|
||||||
|
use: [
|
||||||
|
MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
enforce: 'pre',
|
||||||
|
test: /\.js$/,
|
||||||
|
use: ['source-map-loader'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.js$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
loader: 'babel-loader'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.html$/,
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: 'html-loader',
|
||||||
|
options: {
|
||||||
|
interpolate: true,
|
||||||
|
minimize: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(woff|woff2|eot|ttf|otf|png|svg|jpg|gif)$/,
|
||||||
|
use: ['file-loader']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new MiniCssExtractPlugin({
|
||||||
|
filename: 'style.css',
|
||||||
|
chunkFilename: 'style.css',
|
||||||
|
ignoreOrder: false
|
||||||
|
}),
|
||||||
|
new PurgecssPlugin({
|
||||||
|
paths: glob.sync(`${PATHS.src}/**/*`, { nodir: true }),
|
||||||
|
}),
|
||||||
|
new HtmlWebPackPlugin({
|
||||||
|
template: './src/index.html',
|
||||||
|
filename: './index.html'
|
||||||
|
}),
|
||||||
|
new FaviconsWebpackPlugin('./src/img/icon.png'),
|
||||||
|
new webpack.NoEmitOnErrorsPlugin(),
|
||||||
|
new webpack.WatchIgnorePlugin(['./dist'])
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argv.mode == 'development') {
|
||||||
|
config.devtool = 'inline-source-map'
|
||||||
|
|
||||||
|
config.devServer = {
|
||||||
|
watchContentBase: true,
|
||||||
|
historyApiFallback: true,
|
||||||
|
hot: true,
|
||||||
|
inline: true,
|
||||||
|
|
||||||
|
host: '0.0.0.0',
|
||||||
|
port: 3000
|
||||||
|
}
|
||||||
|
|
||||||
|
config.plugins.push(new webpack.HotModuleReplacementPlugin())
|
||||||
|
config.plugins.push(new OpenBrowserPlugin({
|
||||||
|
url: 'http://localhost:3000'
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argv.mode == 'production') {
|
||||||
|
config.optimization = {
|
||||||
|
minimizer: [
|
||||||
|
new TerserPlugin({
|
||||||
|
cache: true,
|
||||||
|
parallel: true,
|
||||||
|
sourceMap: true
|
||||||
|
}),
|
||||||
|
new OptimizeCSSAssetsPlugin({})
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return config
|
||||||
|
}
|
||||||