Migrate from webpack to esbuild

This commit is contained in:
Adrian Kumpf
2021-09-22 21:24:04 +02:00
parent 7c0dc3b870
commit 70468ea762
30 changed files with 433 additions and 4148 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ Dockerfile
Makefile
README*
test/
priv/static/
priv/static/assets
**/node_modules
import/
teslamate.bck
+1 -1
View File
@@ -31,7 +31,7 @@ npm-debug.log
# Since we are building assets from assets/,
# we ignore priv/static. You may want to comment
# this depending on your deployment strategy.
/priv/static/
/priv/static/assets
# CDLR data repository
/priv/cldr/
+2 -2
View File
@@ -22,8 +22,8 @@ COPY assets/package.json assets/package-lock.json ./assets/
RUN npm ci --prefix ./assets --progress=false --no-audit --loglevel=error
COPY assets assets
RUN npm run deploy --prefix ./assets && \
mix phx.digest
COPY priv/static priv/static
RUN mix assets.deploy
COPY lib lib
COPY priv/repo/migrations priv/repo/migrations
-5
View File
@@ -1,5 +0,0 @@
{
"presets": [
"@babel/preset-env"
]
}
+29 -29
View File
@@ -1,19 +1,19 @@
@charset "utf-8";
@import "~leaflet/dist/leaflet.css";
@import "~leaflet-control-geocoder/dist/Control.Geocoder.css";
@import "~@geoman-io/leaflet-geoman-free/dist/leaflet-geoman.css";
@import "leaflet/dist/leaflet.css";
@import "leaflet-control-geocoder/dist/Control.Geocoder.css";
@import "@geoman-io/leaflet-geoman-free/dist/leaflet-geoman.css";
$mdi-font-path: "~@mdi/font/fonts";
@import "~@mdi/font/scss/materialdesignicons.scss";
$mdi-font-path: "@mdi/font/fonts";
@import "@mdi/font/scss/materialdesignicons.scss";
$notification-padding: 0.75rem 1.25rem 0.75rem 0.75rem;
$widescreen-enabled: false;
$fullhd-enabled: false;
@import "~bulma/sass/utilities/_all";
@import "~bulma/sass/base/_all";
@import "~bulma/sass/helpers/_all.sass";
@import "bulma/sass/utilities/_all";
@import "bulma/sass/base/_all";
@import "bulma/sass/helpers/_all.sass";
// Modal customization
$modal-z: 1010;
@@ -24,28 +24,28 @@ $modal-card-head-background-color: $white;
$modal-card-head-border-bottom: none;
$modal-card-foot-border-top: none;
@import "~bulma/sass/components/breadcrumb";
@import "~bulma/sass/components/card";
@import "~bulma/sass/components/dropdown";
@import "~bulma/sass/components/message";
@import "~bulma/sass/components/modal";
@import "~bulma/sass/components/navbar";
@import "~bulma/sass/components/tabs";
@import "~bulma/sass/elements/box";
@import "~bulma/sass/elements/button";
@import "~bulma/sass/elements/container";
@import "~bulma/sass/elements/icon";
@import "~bulma/sass/elements/notification";
@import "~bulma/sass/elements/table";
@import "~bulma/sass/elements/tag";
@import "~bulma/sass/elements/title";
@import "~bulma/sass/form/_all";
@import "~bulma/sass/layout/section";
@import "~bulma/sass/grid/_all";
@import "bulma/sass/components/breadcrumb";
@import "bulma/sass/components/card";
@import "bulma/sass/components/dropdown";
@import "bulma/sass/components/message";
@import "bulma/sass/components/modal";
@import "bulma/sass/components/navbar";
@import "bulma/sass/components/tabs";
@import "bulma/sass/elements/box";
@import "bulma/sass/elements/button";
@import "bulma/sass/elements/container";
@import "bulma/sass/elements/icon";
@import "bulma/sass/elements/notification";
@import "bulma/sass/elements/table";
@import "bulma/sass/elements/tag";
@import "bulma/sass/elements/title";
@import "bulma/sass/form/_all";
@import "bulma/sass/layout/section";
@import "bulma/sass/grid/_all";
@import "~@creativebulma/bulma-tooltip";
@import "~@creativebulma/bulma-divider";
@import "~bulma-switch";
@import "@creativebulma/bulma-tooltip";
@import "@creativebulma/bulma-divider";
@import "bulma-switch";
@import "./vendor/modal-fx";
+63 -70
View File
@@ -163,7 +163,6 @@ export const SimpleMap = {
const map = createMap({
elId: this.el.dataset.id,
zoomControl: !!this.el.dataset.zoom,
dragging: false,
boxZoom: false,
doubleClickZoom: false,
keyboard: false,
@@ -202,92 +201,86 @@ export const TriggerChange = {
},
};
import("leaflet-control-geocoder");
import("@geoman-io/leaflet-geoman-free");
export const Map = {
mounted() {
Promise.all([
import(
/* webpackPreload: true, webpackChunkName: "geo" */ "leaflet-control-geocoder"
),
import(
/* webpackPreload: true, webpackChunkName: "geo" */ "@geoman-io/leaflet-geoman-free"
),
]).then(() => {
const geoFence = (name) =>
document.querySelector(`input[name='geo_fence[${name}]']`);
const geoFence = (name) =>
document.querySelector(`input[name='geo_fence[${name}]']`);
const $radius = geoFence("radius");
const $latitude = geoFence("latitude");
const $longitude = geoFence("longitude");
const $radius = geoFence("radius");
const $latitude = geoFence("latitude");
const $longitude = geoFence("longitude");
const location = new LatLng($latitude.value, $longitude.value);
const location = new LatLng($latitude.value, $longitude.value);
const controlOpts = {
position: "topleft",
cutPolygon: false,
drawCircle: false,
drawCircleMarker: false,
drawMarker: false,
drawPolygon: false,
drawPolyline: false,
drawRectangle: false,
removalMode: false,
};
const controlOpts = {
position: "topleft",
cutPolygon: false,
drawCircle: false,
drawCircleMarker: false,
drawMarker: false,
drawPolygon: false,
drawPolyline: false,
drawRectangle: false,
removalMode: false,
};
const editOpts = {
allowSelfIntersection: false,
preventMarkerRemoval: true,
};
const editOpts = {
allowSelfIntersection: false,
preventMarkerRemoval: true,
};
const map = createMap({ enableHybridLayer: true });
map.setView(location, 17, { animate: false });
map.pm.setLang(LANG);
map.pm.addControls(controlOpts);
map.pm.enableGlobalEditMode(editOpts);
const map = createMap({ enableHybridLayer: true });
map.setView(location, 17, { animate: false });
map.pm.setLang(LANG);
map.pm.addControls(controlOpts);
map.pm.enableGlobalEditMode(editOpts);
const circle = new Circle(location, { radius: $radius.value })
.addTo(map)
.on("pm:edit", (e) => {
const { lat, lng } = e.target.getLatLng();
const radius = Math.round(e.target.getRadius());
const circle = new Circle(location, { radius: $radius.value })
.addTo(map)
.on("pm:edit", (e) => {
const { lat, lng } = e.target.getLatLng();
const radius = Math.round(e.target.getRadius());
$radius.value = radius;
$latitude.value = lat;
$longitude.value = lng;
$radius.value = radius;
$latitude.value = lat;
$longitude.value = lng;
const mBox = map.getBounds();
const cBox = circle.getBounds();
const bounds = mBox.contains(cBox) ? mBox : cBox;
map.fitBounds(bounds);
});
const mBox = map.getBounds();
const cBox = circle.getBounds();
const bounds = mBox.contains(cBox) ? mBox : cBox;
map.fitBounds(bounds);
});
new Control.geocoder({ defaultMarkGeocode: false })
.on("markgeocode", (e) => {
const { bbox, center } = e.geocode;
new Control.geocoder({ defaultMarkGeocode: false })
.on("markgeocode", (e) => {
const { bbox, center } = e.geocode;
const poly = L.polygon([
bbox.getSouthEast(),
bbox.getNorthEast(),
bbox.getNorthWest(),
bbox.getSouthWest(),
]);
const poly = L.polygon([
bbox.getSouthEast(),
bbox.getNorthEast(),
bbox.getNorthWest(),
bbox.getSouthWest(),
]);
circle.setLatLng(center);
circle.setLatLng(center);
const lBox = poly.getBounds();
const cBox = circle.getBounds();
const bounds = cBox.contains(lBox) ? cBox : lBox;
const lBox = poly.getBounds();
const cBox = circle.getBounds();
const bounds = cBox.contains(lBox) ? cBox : lBox;
map.fitBounds(bounds);
map.pm.enableGlobalEditMode();
map.fitBounds(bounds);
map.pm.enableGlobalEditMode();
const { lat, lng } = center;
$latitude.value = lat;
$longitude.value = lng;
})
.addTo(map);
const { lat, lng } = center;
$latitude.value = lat;
$longitude.value = lng;
})
.addTo(map);
map.fitBounds(circle.getBounds(), { animate: false });
});
map.fitBounds(circle.getBounds(), { animate: false });
},
};
+246 -3926
View File
File diff suppressed because it is too large Load Diff
+6 -18
View File
@@ -1,17 +1,16 @@
{
"repository": {},
"description": "...",
"license": "MIT",
"scripts": {
"deploy": "webpack --mode production --stats-colors",
"watch": " webpack --mode development --watch --watch-options-stdin --stats-colors"
"deploy": "node scripts/build.js"
},
"dependencies": {
"@creativebulma/bulma-divider": "^1.1.0",
"@creativebulma/bulma-tooltip": "^1.2.0",
"@geoman-io/leaflet-geoman-free": "^2.11.2",
"@mdi/font": "^5.9.55",
"@mdi/font": "^6.1.95",
"bulma-switch": "^2.0.0",
"glob": "^7.1.7",
"leaflet": "^1.7.1",
"leaflet-control-geocoder": "^2.3.0",
"phoenix": "file:../deps/phoenix",
@@ -19,21 +18,10 @@
"phoenix_live_view": "file:../deps/phoenix_live_view"
},
"devDependencies": {
"@babel/core": "^7.14.6",
"@babel/preset-env": "^7.14.7",
"babel-loader": "^8.2.2",
"bulma": "^0.9.3",
"copy-webpack-plugin": "^9.0.1",
"css-loader": "^5.2.6",
"css-minimizer-webpack-plugin": "^3.0.2",
"file-loader": "^6.2.0",
"mini-css-extract-plugin": "^1.6.2",
"sass": "^1.35.1",
"sass-loader": "^12.1.0",
"terser-webpack-plugin": "^5.1.4",
"url-loader": "^4.1.1",
"webpack": "^5.41.1",
"webpack-cli": "^4.7.2"
"esbuild": "^0.13.0",
"esbuild-sass-plugin": "^1.5.5",
"sass": "^1.42.1"
},
"name": "assets"
}
+52
View File
@@ -0,0 +1,52 @@
const fs = require("fs");
const path = require("path");
const { sassPlugin } = require("esbuild-sass-plugin");
const esbuild = require("esbuild");
const ENTRY_FILE = "app.js";
const OUTPUT_DIR = path.resolve(__dirname, "../../priv/static/assets");
const OUTPUT_FILE = "app.js";
const MODE = process.env["NODE_ENV"] || "production";
const TARGET = "es2016";
const isDevMode = MODE === "development";
const build_opts = {
entryPoints: [path.join(__dirname, "..", "js", ENTRY_FILE)],
outfile: `${OUTPUT_DIR}/${OUTPUT_FILE}`,
minify: !isDevMode,
watch: isDevMode,
bundle: true,
target: TARGET,
logLevel: "silent",
loader: {
".png": "dataurl",
".ttf": "file",
".otf": "file",
".svg": "file",
".eot": "file",
".woff": "file",
".woff2": "file",
},
plugins: [sassPlugin()],
define: {
"process.env.NODE_ENV": isDevMode ? '"development"' : '"production"',
global: "window",
},
sourcemap: isDevMode,
};
async function build() {
try {
console.log(`[+] Starting static assets build with esbuild (${MODE})...`);
await esbuild.build(build_opts);
console.log(`[+] Esbuild ${ENTRY_FILE} to ${OUTPUT_DIR} succeeded.`);
} catch (e) {
console.error("[-] Error building:", e.message);
process.exit(1);
}
}
if (!fs.existsSync(OUTPUT_DIR)) fs.mkdirSync(OUTPUT_DIR);
build();
-65
View File
@@ -1,65 +0,0 @@
const path = require("path");
const glob = require("glob");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = (env, options) => ({
optimization: {
minimize: true,
minimizer: [`...`, new TerserPlugin(), new CssMinimizerPlugin()],
},
entry: {
app: glob.sync("./vendor/**/*.js").concat(["./js/app.js"]),
},
output: {
publicPath: "/js/",
path: path.resolve(__dirname, "../priv/static/js"),
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
},
{
test: /\.s(c|a)ss$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "sass-loader",
options: {
implementation: require("sass"),
},
},
],
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: "url-loader",
options: {
limit: 10000,
name: "../images/[name].[contenthash:7].[ext]",
},
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: "url-loader",
options: {
limit: 10000,
name: "../fonts/[name].[contenthash:7].[ext]",
},
},
],
},
plugins: [
new MiniCssExtractPlugin({ filename: "../css/app.css" }),
new CopyWebpackPlugin({ patterns: [{ from: "static/", to: "../" }] }),
],
});
+5 -8
View File
@@ -5,14 +5,11 @@ config :teslamate, TeslaMateWeb.Endpoint,
code_reloader: true,
check_origin: false,
watchers: [
node: [
"node_modules/webpack/bin/webpack.js",
"--mode",
"development",
"--stats-colors",
"--watch",
"--watch-options-stdin",
cd: Path.expand("../assets", __DIR__)
npm: [
"run",
"deploy",
cd: Path.expand("../assets", __DIR__),
env: %{"NODE_ENV" => "development"}
]
],
live_reload: [
+1 -1
View File
@@ -13,7 +13,7 @@ defmodule TeslaMateWeb.Endpoint do
socket "/live", Phoenix.LiveView.Socket,
websocket: [connect_info: [session: @session_options], transport_log: :debug]
@only ~w(css fonts images js favicon.ico robots.txt android-chrome-192x192.png
@only ~w(assets fonts images favicon.ico robots.txt android-chrome-192x192.png
android-chrome-512x512.png apple-touch-icon.png browserconfig.xml
favicon-16x16.png favicon-32x32.png mstile-150x150.png
safari-pinned-tab.svg site.webmanifest)
@@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<%= live_title_tag assigns[:page_title] || "Home", suffix: " · TeslaMate" %>
<link rel="stylesheet" href={Routes.static_path(@conn, "/css/app.css")}/>
<link phx-track-static rel="stylesheet" href={Routes.static_path(@conn, "/assets/app.css")}/>
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png?v=5AB53N3ALo">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png?v=5AB53N3ALo">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png?v=5AB53N3ALo">
@@ -15,7 +15,7 @@
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="theme-color" content="#ffffff">
<%= csrf_meta_tag() %>
<script defer src={Routes.static_path(@conn, "/js/app.js")}></script>
<script defer phx-track-static type="text/javascript" src={Routes.static_path(@conn, "/assets/app.js")}></script>
</head>
<body tabIndex="0">
<nav class="navbar is-dark" role="navigation" aria-label="main navigation">
+3 -1
View File
@@ -66,9 +66,11 @@ defmodule TeslaMate.MixProject do
defp aliases do
[
setup: ["deps.get", "ecto.setup", "cmd --cd assets npm ci --no-audit --loglevel=error"],
"ecto.setup": ["ecto.create", "ecto.migrate"],
"ecto.reset": ["ecto.drop", "ecto.setup"],
test: ["ecto.create --quiet", "ecto.migrate", "test --no-start"],
"assets.deploy": ["cmd --cd assets npm run deploy", "phx.digest"],
test: ["ecto.create --quiet", "ecto.migrate --quiet", "test --no-start"],
ci: ["format --check-formatted", "test --raise"]
]
end

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Before

Width:  |  Height:  |  Size: 679 B

After

Width:  |  Height:  |  Size: 679 B

Before

Width:  |  Height:  |  Size: 297 B

After

Width:  |  Height:  |  Size: 297 B

Before

Width:  |  Height:  |  Size: 473 B

After

Width:  |  Height:  |  Size: 473 B

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Before

Width:  |  Height:  |  Size: 524 B

After

Width:  |  Height:  |  Size: 524 B

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Before

Width:  |  Height:  |  Size: 851 B

After

Width:  |  Height:  |  Size: 851 B

+4 -9
View File
@@ -6,26 +6,21 @@ sidebar_label: Development and Contributing
## Requirements
- **Elixir** >= 1.11
- **Elixir** >= 1.12
- **Postgres** >= 10
- An **MQTT broker** e.g. mosquitto (_optional_)
- **NodeJS** >= 14
## Initial Setup
To run the TeslaMate test suite you need a database named `teslamate_test`:
```bash
# download dependencies
mix deps.get
# create the dev database and run migrations
mix ecto.setup
# download dependencies, create the dev database and run migrations
mix setup
# create the test database
MIX_ENV=test mix ecto.setup
# download JavaScript dependencies
npm install --prefix ./assets
```
## Running locally
+2 -2
View File
@@ -77,10 +77,10 @@ Source: [mosquitto.org/download](https://mosquitto.org/download/)
</details>
<details>
<summary>Node.js (v12+)</summary>
<summary>Node.js (v14+)</summary>
```bash
curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
sudo apt-get install -y nodejs
```
+16 -8
View File
@@ -17,8 +17,9 @@ Click on the following items to view detailed installation steps.
pkg install bash
bash
```
For simplicity reasons, follow the rest of the tutorial in bash rather the csh.
For simplicity reasons, follow the rest of the tutorial in bash rather the csh.
</details>
<details>
@@ -27,6 +28,7 @@ bash
```bash
pkg install git
```
</details>
<details>
@@ -35,6 +37,7 @@ pkg install git
```bash
pkg install erlang
```
</details>
<details>
@@ -43,12 +46,12 @@ pkg install erlang
Unfortunately the Elixir part is not well updated in FreeBSD ports.
Hence the latest supported version for Erlang 21 (latest in FreeBSD ports)
is Elixir 1.11.
We will need to compile it from source, which is pretty easy though.
```bash
pkg install gmake
cd /usr/local/src
git clone https://github.com/elixir-lang/elixir.git
cd elixir
@@ -57,6 +60,7 @@ gmake clean test
gmake install
elixir --version
```
</details>
<details>
@@ -66,7 +70,7 @@ elixir --version
pkg install postgressql(12|13)-server
echo postgres_enable="yes" >> /etc/rc.conf
```
</details>
<details>
@@ -76,6 +80,7 @@ echo postgres_enable="yes" >> /etc/rc.conf
pkg install grafana7
echo grafana_enable="yes" >> /etc/rc.conf
```
</details>
<details>
@@ -89,11 +94,12 @@ echo mosquitto_enable="yes" >> /etc/rc.conf
</details>
<details>
<summary>Node.js (v12+)</summary>
<summary>Node.js (v14+)</summary>
```bash
pkg install node(12|14|)
```
</details>
## Clone TeslaMate git repository
@@ -139,6 +145,7 @@ mix do phx.digest, release --overwrite
## Starting TeslaMate at boot time
### Create FreeBSD service definition _/usr/local/etc/rc.d/teslamate_
```console
# PROVIDE: teslamate
# REQUIRE: DAEMON
@@ -183,7 +190,7 @@ COMMAND=${teslamate_command-"${HOME}/_build/prod/rel/teslamate/bin/teslamate"}
teslamate_start()
{
${COMMAND} eval "TeslaMate.Release.migrate"
${COMMAND} daemon
${COMMAND} daemon
}
start_cmd="${name}_start"
@@ -196,6 +203,7 @@ run_rc_command "$1"
```
### Update _/etc/rc.conf_
```bash
echo teslamate_enable="YES" >> /etc/rc.conf
echo teslamate_db_host="localhost" >> /etc/rc.conf
@@ -205,6 +213,7 @@ echo teslamate_disable_mqtt="true" >> /etc/rc.conf
```
### Start service
```bash
service teslamate start
```
@@ -261,4 +270,3 @@ service teslamate start
```
:::