- webpack config separation for development and production
- load only the necessary classes from leaflet
This commit is contained in:
parent
7857e2c5bb
commit
bc44385846
13 changed files with 883 additions and 209 deletions
23
notes.txt
23
notes.txt
|
@ -125,3 +125,26 @@ Install dependencies
|
|||
|
||||
|
||||
npm install --save rxjs
|
||||
|
||||
npm install --save-dev webpack-merge
|
||||
|
||||
========================= cretae html file for production
|
||||
https://webpack.js.org/plugins/html-webpack-plugin/
|
||||
|
||||
npm install --save-dev html-webpack-plugin
|
||||
|
||||
Basic Usage:
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
entry: 'index.js',
|
||||
output: {
|
||||
path: path.resolve(__dirname, './dist'),
|
||||
filename: 'index_bundle.js',
|
||||
},
|
||||
plugins: [new HtmlWebpackPlugin()],
|
||||
};
|
||||
|
||||
This will generate a file dist/index.html containing the following:
|
||||
|
||||
|
|
772
package-lock.json
generated
772
package-lock.json
generated
File diff suppressed because it is too large
Load diff
10
package.json
10
package.json
|
@ -5,8 +5,8 @@
|
|||
"main": "index.ts",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"prod": "rm -rf dist && webpack --progress --mode=production",
|
||||
"dev": "webpack serve --mode development --content-base=./ --hot --progress --port 8080"
|
||||
"prod": "rm -rf dist && webpack --progress --config webpack.production.js",
|
||||
"dev": "webpack serve --config webpack.development.js --content-base=./ --hot --progress --port 8080"
|
||||
},
|
||||
"keywords": [
|
||||
"geomonitoring",
|
||||
|
@ -29,6 +29,7 @@
|
|||
"dotenv": "^10.0.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"html-loader": "^2.1.2",
|
||||
"html-webpack-plugin": "^5.3.2",
|
||||
"img-loader": "^4.0.0",
|
||||
"mini-css-extract-plugin": "^2.1.0",
|
||||
"raw-loader": "^4.0.2",
|
||||
|
@ -37,7 +38,8 @@
|
|||
"url-loader": "^4.1.1",
|
||||
"webpack": "^5.47.0",
|
||||
"webpack-cli": "^4.7.2",
|
||||
"webpack-dev-server": "^3.11.2"
|
||||
"webpack-dev-server": "^3.11.2",
|
||||
"webpack-merge": "^5.8.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/core": "^12.1.4",
|
||||
|
@ -52,7 +54,7 @@
|
|||
"babel-plugin-transform-typescript-metadata": "^0.3.2",
|
||||
"core-js": "^3.16.0",
|
||||
"leaflet": "^1.7.1",
|
||||
"rxjs": "^6.6.7",
|
||||
"rxjs": "^7.3.0",
|
||||
"zone.js": "^0.11.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<app-map [mapId]="'map'" [mapOptions]="mapOptions" [serviceUrl]="providerUrl" [baseMaps]="baseMaps" (mapInitializedEvent)="mapInitialized($event)"></app-map>
|
||||
<app-map [mapId]="'map'" [mapOptions]="mapOptions" [serviceUrl]="providerUrl" [baseMaps]="baseMaps"
|
||||
(onSelected)="onStationSelected($event)" (onMapInitializedEvent)="onMapInitialized($event)"></app-map>
|
||||
<!-- <span>{{ name }} app is running!</span> -->
|
||||
|
||||
<!-- <div>
|
||||
|
|
|
@ -4,9 +4,10 @@ import '../styles.css';
|
|||
|
||||
import { ParameterFilter, Phenomenon, Station } from '@helgoland/core';
|
||||
import { GeoSearchOptions, LayerOptions } from '@helgoland/map';
|
||||
import * as L from 'leaflet';
|
||||
import { Marker, MapOptions, Control, icon, LatLngBoundsExpression } from 'leaflet';
|
||||
// optional, to adapt leaflet markers
|
||||
L.Marker.prototype.options.icon = L.icon({
|
||||
|
||||
Marker.prototype.options.icon = icon({
|
||||
iconRetinaUrl: 'assets/img/marker-icon-2x.png',
|
||||
iconUrl: 'assets/img/marker-icon.png',
|
||||
shadowUrl: 'assets/img/marker-shadow.png',
|
||||
|
@ -39,25 +40,25 @@ export class AppComponent {
|
|||
// public providerUrl = 'https://geo.irceline.be/sos/api/v2/';
|
||||
public providerUrl = 'https://geomon.geologie.ac.at/52n-sos-webapp/api/';
|
||||
|
||||
public fitBounds: L.LatLngBoundsExpression = [[49.5, 3.27], [51.5, 5.67]];
|
||||
public fitBounds: LatLngBoundsExpression = [[ 9.47996951665, 46.4318173285], [16.9796667823, 49.0390742051]];
|
||||
// public zoomControlOptions: L.Control.ZoomOptions = { position: 'topleft' };
|
||||
public avoidZoomToSelection = false;
|
||||
public baseMaps: Map<string, LayerOptions> = new Map<string, LayerOptions>();
|
||||
public overlayMaps: Map<string, LayerOptions> = new Map<string, LayerOptions>();
|
||||
public layerControlOptions: L.Control.LayersOptions = { position: 'bottomleft' };
|
||||
public layerControlOptions: Control.LayersOptions = { position: 'bottomleft' };
|
||||
public cluster = false;
|
||||
public loadingStations: boolean;
|
||||
public stationFilter: ParameterFilter = {
|
||||
// phenomenon: '8'
|
||||
};
|
||||
public statusIntervals = false;
|
||||
public mapOptions: L.MapOptions = { dragging: true, zoomControl: false };
|
||||
public mapOptions: MapOptions = { dragging: true, zoomControl: false };
|
||||
|
||||
public onStationSelected(station: Station) {
|
||||
private onStationSelected(station: Station) {
|
||||
console.log('Clicked station: ' + station.properties.label);
|
||||
}
|
||||
|
||||
mapInitialized(newItem: string) {
|
||||
private onMapInitialized(newItem: string) {
|
||||
// alert(newItem);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,10 +4,6 @@ import { BrowserModule } from "@angular/platform-browser";
|
|||
import { AppComponent } from './app.component';
|
||||
import { MapComponent } from './map/map.component';
|
||||
|
||||
// import {
|
||||
// HelgolandServicesConnector
|
||||
// } from '@helgoland/core';
|
||||
|
||||
import { HttpClientModule, HttpClient } from '@angular/common/http'; //for http requests
|
||||
import { MarkerService } from './services/marker.service';
|
||||
import { DatasetApiService } from "./services/dataset-api.service";
|
||||
|
@ -16,10 +12,10 @@ import { HttpService } from "./services/http.service";
|
|||
// siehe https://52north.github.io/helgoland-toolbox/additional-documentation/how-tos/integrate-a-map-component.html
|
||||
// https://52north.github.io/helgoland-toolbox/components/LocateControlComponent.html#source
|
||||
|
||||
import {
|
||||
DatasetApiInterface, ApiV3InterfaceService, SplittedDataDatasetApiInterface, DatasetApiV3Connector, HelgolandServicesConnector
|
||||
} from '@helgoland/core';
|
||||
import { HelgolandCoreModule } from "@helgoland/core";
|
||||
// import {
|
||||
// DatasetApiInterface, ApiV3InterfaceService, SplittedDataDatasetApiInterface, DatasetApiV3Connector, HelgolandServicesConnector
|
||||
// } from '@helgoland/core';
|
||||
// import { HelgolandCoreModule } from "@helgoland/core";
|
||||
|
||||
// import 'core-js';
|
||||
|
||||
|
@ -27,7 +23,7 @@ import { HelgolandCoreModule } from "@helgoland/core";
|
|||
// declarations: The components, directives, and pipes that belong to this NgModule.
|
||||
declarations: [AppComponent, MapComponent],
|
||||
// imports: Other modules whose exported classes are needed by component templates declared in this NgModule.
|
||||
imports: [BrowserModule, HttpClientModule, HelgolandCoreModule],
|
||||
imports: [BrowserModule, HttpClientModule],
|
||||
providers: [
|
||||
MarkerService, HttpService, DatasetApiService,
|
||||
// {
|
||||
|
@ -36,11 +32,11 @@ import { HelgolandCoreModule } from "@helgoland/core";
|
|||
// deps: [HttpXhrBackend]
|
||||
// },
|
||||
|
||||
{
|
||||
provide: HelgolandServicesConnector,
|
||||
useClass: DatasetApiV3Connector,
|
||||
deps: [HttpClient]
|
||||
},
|
||||
// {
|
||||
// provide: HelgolandServicesConnector,
|
||||
// useClass: DatasetApiV3Connector,
|
||||
// deps: [HttpClient]
|
||||
// },
|
||||
|
||||
],
|
||||
// bootstrap: The main application view, called the root component, which hosts all other application views.
|
||||
|
|
|
@ -70,7 +70,7 @@ export abstract class BaseMapComponent implements OnChanges, OnInit {
|
|||
* Informs when initialization is done with map id.
|
||||
*/
|
||||
@Output()
|
||||
public mapInitializedEvent: EventEmitter<string> = new EventEmitter();
|
||||
public onMapInitializedEvent: EventEmitter<string> = new EventEmitter();
|
||||
|
||||
protected oldBaseLayer: L.Control.LayersObject = {};
|
||||
protected map: L.Map;
|
||||
|
@ -103,7 +103,7 @@ export abstract class BaseMapComponent implements OnChanges, OnInit {
|
|||
zoom: 3
|
||||
});
|
||||
|
||||
this.mapInitializedEvent.emit(this.mapId);
|
||||
this.onMapInitializedEvent.emit(this.mapId);
|
||||
if (this.baseMaps && this.baseMaps.size > 0) {
|
||||
this.baseMaps.forEach((layerOptions, key) => this.addBaseMap(layerOptions));
|
||||
} else {
|
||||
|
|
|
@ -1,24 +1,10 @@
|
|||
// https://github.com/52North/helgoland-toolbox/blob/c2c2eda20353c469a7aa4a6a118a810723af6622/libs/map/src/lib/selector/station-map-selector/station-map-selector.component.ts
|
||||
import { Component, AfterViewInit, OnChanges, SimpleChanges, EventEmitter, Input, Output } from '@angular/core';
|
||||
import * as L from 'leaflet';
|
||||
import { Map, Control, FeatureGroup, geoJSON, circleMarker, FitBoundsOptions, LatLngBoundsExpression } from 'leaflet';
|
||||
import { MarkerService } from '../services/marker.service';
|
||||
import { DatasetApiService } from '../services/dataset-api.service';
|
||||
import { BaseMapComponent } from './base-map.component';
|
||||
|
||||
// const iconRetinaUrl = 'assets/marker-icon-2x.png';
|
||||
// const iconUrl = 'assets/marker-icon.png';
|
||||
// const shadowUrl = 'assets/marker-shadow.png';
|
||||
// const iconDefault = L.icon({
|
||||
// iconRetinaUrl,
|
||||
// iconUrl,
|
||||
// shadowUrl,
|
||||
// iconSize: [25, 41],
|
||||
// iconAnchor: [12, 41],
|
||||
// popupAnchor: [1, -34],
|
||||
// tooltipAnchor: [16, -28],
|
||||
// shadowSize: [41, 41]
|
||||
// });
|
||||
// L.Marker.prototype.options.icon = iconDefault;
|
||||
|
||||
@Component({
|
||||
selector: 'app-map',
|
||||
templateUrl: './map.component.html',
|
||||
|
@ -41,17 +27,22 @@ export class MapComponent
|
|||
@Input()
|
||||
public serviceUrl: string;
|
||||
|
||||
// @Output()
|
||||
// public onSelected: EventEmitter<T> = new EventEmitter<T>();
|
||||
@Output()
|
||||
public onSelected: EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
@Output()
|
||||
public onContentLoadingEvent: EventEmitter<boolean> = new EventEmitter();
|
||||
|
||||
/**
|
||||
* @input Additional configuration for the marker zooming (https://leafletjs.com/reference-1.3.4.html#fitbounds-options)
|
||||
*/
|
||||
@Input()
|
||||
public fitBoundsMarkerOptions: FitBoundsOptions;
|
||||
|
||||
protected oldBaseLayer: L.Control.LayersObject = {};
|
||||
protected map: L.Map;
|
||||
protected zoomControl: L.Control.Zoom;
|
||||
protected markerFeatureGroup: L.FeatureGroup;
|
||||
protected oldBaseLayer: Control.LayersObject = {};
|
||||
protected map: Map;
|
||||
protected zoomControl: Control.Zoom;
|
||||
protected markerFeatureGroup: FeatureGroup;
|
||||
|
||||
// constructor() { }
|
||||
constructor(
|
||||
|
@ -69,20 +60,27 @@ export class MapComponent
|
|||
// this.markerService.makeCapitalCircleMarkers(this.map);
|
||||
this.datasetApiService.getStations('https://geomon.geologie.ac.at/52n-sos-webapp/api/')
|
||||
.subscribe((res) => {
|
||||
this.markerFeatureGroup = L.featureGroup();
|
||||
this.markerFeatureGroup = new FeatureGroup();
|
||||
if (res instanceof Array && res.length > 0) {
|
||||
res.forEach((entry) => {
|
||||
res.forEach((station) => {
|
||||
//const marker = this.createDefaultGeometry(entry);
|
||||
// const marker = L.geoJSON(entry.geometry);
|
||||
const marker = L.geoJSON(entry.geometry, {
|
||||
// const marker = geoJSON(entry.geometry);
|
||||
const marker = geoJSON(station.geometry, {
|
||||
pointToLayer: function (feature, latlng) {
|
||||
return L.circleMarker(latlng);
|
||||
return circleMarker(latlng);
|
||||
}
|
||||
})
|
||||
if (marker) { this.markerFeatureGroup.addLayer(marker); }
|
||||
// if (marker) { this.markerFeatureGroup.addLayer(marker); }
|
||||
marker && this.markerFeatureGroup.addLayer(marker);
|
||||
if (marker) {
|
||||
marker.on('click', () => {
|
||||
this.onSelected.emit(station);
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
this.markerFeatureGroup.addTo(this.map);
|
||||
// this.zoomToMarkerBounds(this.markerFeatureGroup.getBounds());
|
||||
this.zoomToMarkerBounds(this.markerFeatureGroup.getBounds());
|
||||
} else {
|
||||
// this.onNoResultsFound.emit(true);
|
||||
}
|
||||
|
@ -108,4 +106,14 @@ export class MapComponent
|
|||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Zooms to the given bounds
|
||||
*
|
||||
* @protected
|
||||
* @param bounds where to zoom
|
||||
*/
|
||||
protected zoomToMarkerBounds(bounds: LatLngBoundsExpression) {
|
||||
this.map.fitBounds(bounds, this.fitBoundsMarkerOptions || {});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import * as L from 'leaflet';
|
||||
import { Map, circleMarker } from 'leaflet';
|
||||
|
||||
// @Injectable({
|
||||
// // declares that this service should be created
|
||||
|
@ -33,7 +33,7 @@ export class MarkerService {
|
|||
// });
|
||||
// }
|
||||
|
||||
makeCapitalCircleMarkers(map: L.Map): void {
|
||||
makeCapitalCircleMarkers(map: Map): void {
|
||||
this.http.get(this.capitalsUrl).subscribe((res: any) => {
|
||||
|
||||
let maxPop = Math.max(...res.features.map(x => x.properties.population), 0);
|
||||
|
@ -42,7 +42,7 @@ export class MarkerService {
|
|||
const lon = c.geometry.coordinates[0];
|
||||
const lat = c.geometry.coordinates[1];
|
||||
// const circle = L.circleMarker([lat, lon]);
|
||||
let circle = L.circleMarker([lat, lon], {
|
||||
let circle = circleMarker([lat, lon], {
|
||||
radius: MarkerService.scaledRadius(c.properties.population, maxPop)
|
||||
});
|
||||
circle.addTo(map);
|
||||
|
|
40
src/index.tmp.html
Normal file
40
src/index.tmp.html
Normal file
|
@ -0,0 +1,40 @@
|
|||
<!doctype html>
|
||||
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
|
||||
<title><%= htmlWebpackPlugin.options.title || 'Webpack App'%></title>
|
||||
<meta name="description" content="A simple HTML5 Template for new projects.">
|
||||
<meta name="author" content="Arno Kaimbacher">
|
||||
|
||||
<meta property="og:title" content="GeoMon Viewer">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="https://geomon.geologie.ac.at/52n-sos-webapp/">
|
||||
<meta property="og:description" content="A simple HTML5 Template for new projects.">
|
||||
<meta property="og:image" content="image.png">
|
||||
|
||||
|
||||
|
||||
<link rel="icon" href="src/favicon.ico">
|
||||
<!-- <link rel="icon" href="/favicon.svg" type="image/svg+xml">
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png"> -->
|
||||
|
||||
<!-- <link rel="stylesheet" href="./node_modules/leaflet//dist/leaflet.css"> -->
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- your content here... -->
|
||||
<app-component></app-component>
|
||||
|
||||
<!-- <script src="dist/polyfills.js" defer></script> -->
|
||||
<!-- <script src="dist/main.js"></script> -->
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -8,8 +8,8 @@ const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
|||
/**
|
||||
* flag Used to check if the environment is production or not
|
||||
*/
|
||||
const isProduction = false; //(process.env.NODE_ENV === 'production');
|
||||
const devMode = (process.env.NODE_ENV !== 'production');
|
||||
const isProduction = (process.env.NODE_ENV === 'production');
|
||||
// const devMode = (process.env.NODE_ENV !== 'production');
|
||||
|
||||
/**
|
||||
* Include hash to filenames for cache busting - only at production
|
||||
|
@ -33,14 +33,6 @@ module.exports = {
|
|||
publicPath: '/dist/',
|
||||
// sourceMapFilename: "[name].js.map"
|
||||
},
|
||||
devServer: {
|
||||
contentBase: path.resolve(__dirname),
|
||||
publicPath: "/", //should provide the path of the served js , img , etc...
|
||||
writeToDisk: true,
|
||||
compress: true,
|
||||
port: 8080,
|
||||
open: true,
|
||||
},
|
||||
|
||||
// resolve: {
|
||||
// alias: {
|
||||
|
@ -126,15 +118,6 @@ module.exports = {
|
|||
},
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
test: /\.(css|scss)$/,
|
||||
// include: helpers.root('src', 'app'),
|
||||
|
@ -178,35 +161,35 @@ module.exports = {
|
|||
resolve: {
|
||||
extensions: ['*', '.js', '.jsx', '.tsx', '.ts'],
|
||||
},
|
||||
devtool: 'inline-source-map',
|
||||
// devtool: 'inline-source-map',
|
||||
stats: {
|
||||
colors: true
|
||||
},
|
||||
|
||||
// optimization: {
|
||||
// minimize: isProduction,
|
||||
// minimizer: [
|
||||
// new TerserPlugin({
|
||||
// // cache: true,
|
||||
// parallel: true,
|
||||
// // sourceMap: true, // Must be set to true if using source-maps in production
|
||||
// extractComments: true,
|
||||
// terserOptions: {
|
||||
optimization: {
|
||||
minimize: isProduction,
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
// cache: true,
|
||||
parallel: true,
|
||||
// sourceMap: true, // Must be set to true if using source-maps in production
|
||||
extractComments: true,
|
||||
terserOptions: {
|
||||
|
||||
// compress: {
|
||||
// directives: false,
|
||||
// // drop_console: true,
|
||||
// // drop_debugger: true,
|
||||
// // keep_classnames: false,
|
||||
// // keep_fnames: false,
|
||||
// },
|
||||
// mangle: true, // Note `mangle.properties` is `false` by default.
|
||||
compress: {
|
||||
directives: false,
|
||||
// drop_console: true,
|
||||
// drop_debugger: true,
|
||||
// keep_classnames: false,
|
||||
// keep_fnames: false,
|
||||
// }
|
||||
// })
|
||||
// ],
|
||||
// },
|
||||
},
|
||||
mangle: true, // Note `mangle.properties` is `false` by default.
|
||||
keep_classnames: false,
|
||||
keep_fnames: false,
|
||||
}
|
||||
})
|
||||
],
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new MiniCssExtractPlugin({ // Make sure MiniCssExtractPlugin instance is included in array before the PurifyCSSPlugin
|
||||
|
@ -217,12 +200,6 @@ module.exports = {
|
|||
filename: '[name].css',
|
||||
chunkFilename: '[chunkhash].css',
|
||||
}),
|
||||
|
||||
// new webpack.LoaderOptionsPlugin({
|
||||
// htmlLoader: {
|
||||
// minimize: false
|
||||
// }
|
||||
// })
|
||||
]
|
||||
};
|
||||
|
17
webpack.development.js
Normal file
17
webpack.development.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
const { merge } = require('webpack-merge');
|
||||
const common = require('./webpack.common.js');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = merge(common, {
|
||||
mode: 'development',
|
||||
devtool: 'inline-source-map',
|
||||
devServer: {
|
||||
contentBase: path.resolve(__dirname),
|
||||
publicPath: "/", //should provide the path of the served js , img , etc...
|
||||
writeToDisk: true,
|
||||
compress: false,
|
||||
port: 8080,
|
||||
open: false,
|
||||
stats: 'errors-only',
|
||||
},
|
||||
});
|
15
webpack.production.js
Normal file
15
webpack.production.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
const { merge } = require('webpack-merge');
|
||||
const common = require('./webpack.common.js');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
|
||||
|
||||
module.exports = merge(common, {
|
||||
mode: 'production',
|
||||
devtool: 'source-map',
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
template: './src/index.tmp.html',
|
||||
title: 'sensor viewer',
|
||||
})
|
||||
],
|
||||
});
|
Loading…
Add table
Reference in a new issue