Fix Docker build JavaScript import errors with vendor bundle
Fixed the esbuild errors during Docker build where npm packages couldn't be resolved. The issue was caused by node_modules being excluded from the Docker build context in .dockerignore. Implemented a proper vendor bundle strategy following Phoenix 1.7+ patterns: - Created vendor.js that bundles all npm dependencies (Leaflet, Chart.js, topbar) and their CSS files into a single pre-built bundle - Added vendor esbuild profile in config.exs with proper CSS/image loaders - Updated mix.exs to build vendor bundle before app bundle in assets.deploy - Modified JavaScript imports to use globally loaded libraries from vendor bundle instead of importing from node_modules - Added vendor.js script tag to root.html.heex before app.js This approach avoids Docker build failures by pre-bundling all vendor dependencies, eliminating the need for node_modules during production builds. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
53ce452cdf
commit
63a87f3be1
7 changed files with 45 additions and 19 deletions
|
|
@ -20,7 +20,8 @@ import "phoenix_html";
|
|||
// Establish Phoenix Socket and LiveView configuration.
|
||||
import { Socket } from "phoenix";
|
||||
import { LiveSocket } from "phoenix_live_view";
|
||||
import topbar from "topbar";
|
||||
// topbar is loaded globally from vendor bundle
|
||||
const topbar = window.topbar;
|
||||
|
||||
// Sentry initialization happens via the loader script in the HTML
|
||||
// Configure additional Sentry settings if needed
|
||||
|
|
|
|||
|
|
@ -1,13 +1,10 @@
|
|||
// Import Chart.js and date adapter
|
||||
import Chart from 'chart.js/auto';
|
||||
import 'chartjs-adapter-date-fns';
|
||||
// Chart.js and date adapter are loaded globally from vendor bundle
|
||||
const Chart = window.Chart;
|
||||
|
||||
import type { ChartConfiguration, ChartType } from 'chart.js';
|
||||
import type { WeatherChartDataset, YAxisOptions } from '../types/chart-types';
|
||||
import type { HandleEventFunction } from '../types/events';
|
||||
|
||||
// Make Chart globally available for legacy code
|
||||
window.Chart = Chart;
|
||||
|
||||
// Declare global Chart object
|
||||
declare global {
|
||||
interface Window {
|
||||
|
|
|
|||
|
|
@ -12,19 +12,10 @@ import type { HeatLayer, MarkerClusterGroup, OverlappingMarkerSpiderfier, Marker
|
|||
import type { APRSMarker } from './types/marker-extensions';
|
||||
import type { BaseEventPayload } from './types/events';
|
||||
|
||||
// Import Leaflet and plugins
|
||||
import L from 'leaflet';
|
||||
import 'leaflet.heat';
|
||||
import 'leaflet.markercluster';
|
||||
import 'overlapping-marker-spiderfier-leaflet';
|
||||
// Leaflet and plugins are loaded globally from vendor bundle
|
||||
const L = window.L;
|
||||
|
||||
// Import CSS files
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import 'leaflet.markercluster/dist/MarkerCluster.css';
|
||||
import 'leaflet.markercluster/dist/MarkerCluster.Default.css';
|
||||
|
||||
// Make Leaflet globally available for legacy code
|
||||
window.L = L;
|
||||
// CSS files are bundled in vendor.js
|
||||
|
||||
// The OverlappingMarkerSpiderfier is attached to window by the UMD module
|
||||
declare global {
|
||||
|
|
|
|||
28
assets/js/vendor.js
Normal file
28
assets/js/vendor.js
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Vendor bundle for all third-party dependencies
|
||||
// This file bundles all npm packages to avoid resolution issues during Docker builds
|
||||
|
||||
// Import CSS files first
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import 'leaflet.markercluster/dist/MarkerCluster.css';
|
||||
import 'leaflet.markercluster/dist/MarkerCluster.Default.css';
|
||||
|
||||
// Export Leaflet and plugins
|
||||
import * as L from 'leaflet';
|
||||
import 'leaflet.heat';
|
||||
import 'leaflet.markercluster';
|
||||
import 'overlapping-marker-spiderfier-leaflet';
|
||||
|
||||
// Export Chart.js and adapter
|
||||
import Chart from 'chart.js/auto';
|
||||
import 'chartjs-adapter-date-fns';
|
||||
|
||||
// Export topbar
|
||||
import topbar from 'topbar';
|
||||
|
||||
// Make libraries available globally
|
||||
window.L = L;
|
||||
window.Chart = Chart;
|
||||
window.topbar = topbar;
|
||||
|
||||
// Export for ES modules
|
||||
export { L, Chart, topbar };
|
||||
|
|
@ -85,6 +85,12 @@ config :esbuild,
|
|||
~w(js/app.js --bundle --target=es2017 --outdir=../priv/static/assets --external:/fonts/* --external:/images/* --loader:.css=css --loader:.png=file --loader:.svg=file),
|
||||
cd: Path.expand("../assets", __DIR__),
|
||||
env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
|
||||
],
|
||||
vendor: [
|
||||
args:
|
||||
~w(js/vendor.js --bundle --target=es2017 --outdir=../priv/static/assets --minify --loader:.css=css --loader:.png=file --loader:.svg=file),
|
||||
cd: Path.expand("../assets", __DIR__),
|
||||
env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
|
||||
]
|
||||
|
||||
config :gettext, :plural_forms, GettextPseudolocalize.Plural
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@
|
|||
{assigns[:page_title] || "Aprs"}
|
||||
</.live_title>
|
||||
<link phx-track-static rel="stylesheet" href={~p"/assets/css/app.css"} />
|
||||
<script defer phx-track-static type="text/javascript" src={~p"/assets/vendor.js"}>
|
||||
</script>
|
||||
<script defer phx-track-static type="text/javascript" src={~p"/assets/app.js"}>
|
||||
</script>
|
||||
<script>
|
||||
|
|
|
|||
1
mix.exs
1
mix.exs
|
|
@ -135,6 +135,7 @@ defmodule Aprsme.MixProject do
|
|||
test: ["gleam_compile", "ecto.create --quiet", "ecto.migrate --quiet", "test"],
|
||||
"assets.deploy": [
|
||||
"tailwind default --minify",
|
||||
"esbuild vendor",
|
||||
"esbuild default --minify",
|
||||
"phx.digest"
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue