diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c163077 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vscode/ +build/ +node_modules/ \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..b2095be --- /dev/null +++ b/.prettierrc @@ -0,0 +1,4 @@ +{ + "semi": false, + "singleQuote": true +} diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..133caad --- /dev/null +++ b/babel.config.js @@ -0,0 +1,8 @@ +module.exports = api => { + // caching the babel config + api.cache.using(() => process.env.NODE_ENV) + return { + presets: ['@babel/preset-env', '@babel/preset-react'] + // plugins: [api.env('development') && 'react-refresh/babel'].filter(Boolean) + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..eb52c8c --- /dev/null +++ b/package.json @@ -0,0 +1,21 @@ +{ + "name": "ebermergen", + "version": "0.1.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "webpack-dev-server --mode development", + "build": "webpack --mode production", + "build-fresh": "rm -rf build/ && npm run build", + "serve": "ws -d build --compress --hostname 0.0.0.0", + "test": "tests", + "lint": "eslint src", + "format": "prettier --write src/**/*.js" + }, + "repository": { + "type": "git", + "url": "git@localhost:ebermergen" + }, + "author": "", + "license": "ISC" +} diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..bff025d --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,7 @@ +module.exports = { + plugins: [ + require('postcss-flexbugs-fixes'), + require('postcss-preset-env'), + require('postcss-normalize') + ] +} diff --git a/src/App.css b/src/App.css new file mode 100644 index 0000000..3377be8 --- /dev/null +++ b/src/App.css @@ -0,0 +1,30 @@ +body, +html { + margin: 0; + padding: 0; + font-family: Arial, Helvetica, sans-serif; + line-height: 1.5; + background-color: #fce6cb; +} + +html { + overflow-y: scroll; +} + +header { + border-bottom: 2px solid white; + margin-bottom: 1em; + display: flex; + align-items: center; + padding: 0px 10px; +} + +header h1 { + flex: 1; +} + +footer { + border-top: 2px solid white; + margin-top: 1em; + padding: 0 10px; +} diff --git a/src/App.js b/src/App.js new file mode 100644 index 0000000..e24581a --- /dev/null +++ b/src/App.js @@ -0,0 +1,17 @@ +import React from 'react' + +import './App.css' + +export const App = () => { + return ( + <> +
+

Ebermergen

+
+
+ +
+ + + ) +} diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..a6fc942 --- /dev/null +++ b/src/index.js @@ -0,0 +1,15 @@ +import 'regenerator-runtime/runtime' + +import React from 'react' +import ReactDOM from 'react-dom' + +import { App } from './App' + +function createRootElement() { + const body = document.getElementsByTagName('body')[0] + const root = document.createElement('div') + root.setAttribute('id', 'root') + body.appendChild(root) + return root +} +ReactDOM.render(, createRootElement()) diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..dba1be0 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,93 @@ +const path = require('path') + +const HtmlWebpackPlugin = require('html-webpack-plugin') +const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin') +const BundleAnalyzerPlugin = require('webpack-bundle-analyzer') + .BundleAnalyzerPlugin +const MiniCssExtractPlugin = require('mini-css-extract-plugin') +const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin') +const WebpackBar = require('webpackbar') + +module.exports = (env, argv) => { + const isEnvProduction = argv.mode === 'production' + const isEnvDevelopment = argv.mode === 'development' + + return { + output: { + path: path.resolve(__dirname, 'build'), + filename: 'static/js/[name].[contenthash:8].js', + chunkFilename: 'static/js/[name].[contenthash:8].chunk.js' + }, + devtool: isEnvProduction ? 'source-map' : 'cheap-module-source-map', + module: { + rules: [ + // process javascript with babel + { + test: /\.js$/, + exclude: /node_modules/, + loader: 'babel-loader' + }, + // process css. css modules are enabled. + { + test: /\.css$/, + use: [ + isEnvDevelopment && 'style-loader', + isEnvProduction && MiniCssExtractPlugin.loader, + { + loader: 'css-loader', + options: { + modules: { + localIdentName: isEnvProduction + ? '[hash:base64]' + : '[path][name]__[local]' + } + } + }, + 'postcss-loader' + ].filter(Boolean) + } + ] + }, + optimization: { + minimize: isEnvProduction, + splitChunks: { + chunks: 'all', + name: false + }, + runtimeChunk: { + name: entrypoint => `runtime-${entrypoint.name}` + } + }, + plugins: [ + // creat an index.html + new HtmlWebpackPlugin(), + // show a progress bar + new WebpackBar(), + // create a report.html for bundle size + // extract css to css files + isEnvProduction && + new MiniCssExtractPlugin({ + filename: 'static/css/[name].[contenthash:8].css', + chunkFilename: 'static/css/[name].[contenthash:8].chunk.css' + }), + // use cssnano to minify css + isEnvProduction && + new OptimizeCssAssetsPlugin({ + cssProcessorOptions: { + map: { inline: false, annotation: true } + } + }), + isEnvProduction && + new BundleAnalyzerPlugin({ + analyzerMode: 'static', + openAnalyzer: false + }) + // hot reload not working right now + // isEnvDevelopment && + // new ReactRefreshWebpackPlugin({ disableRefreshCheck: true }) + ].filter(Boolean), + devServer: { + stats: 'minimal' + } + } +}