Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),

#### Stack-level

- **Docker**: `docker compose build front` uses the Angular 22 viewer webpack config. `envsubst` replaces only `PUBLIC_BASE_PATH`, so the viewer image build keeps the `jszip`, `util`, and `@spz-loader` exclusions.
- **Docker**: `sitmun-shared` checks out `gradlew` with LF line endings. On Windows with `core.autocrlf=true`, the backend and proxy image builds failed in `publishToMavenLocal` with `/bin/sh^M: bad interpreter` (exit code 126) ([#89](https://github.com/sitmun/sitmun-application-stack/issues/89)).
- **E2E**: Each root E2E job publishes the pinned `sitmun-shared` to the local Maven repository before the suite starts. The backend resolves `sitmun-spring-upstream` and `sitmun-proxy-contract` `1.2.9` from that repository.
- **Submodules**: `sitmun-mbtiles` follows the stack branch. `git submodule update --remote` on stack `dev` stays on mbtiles `dev`, the commit the stack already pins.
Expand Down
2 changes: 1 addition & 1 deletion front/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ RUN export BUILD_TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z") && \
if [ "${ENVIRONMENT}" = "production" ]; then export FRONT_ENV=Production; export FRONT_PRODUCTION=true; else export FRONT_ENV=Development; export FRONT_PRODUCTION=false; fi && \
envsubst '$BUILD_TIMESTAMP,$APP_VERSION,$FRONT_ENV,$PUBLIC_BASE_PATH' < ./src/environments/environment.prod.ts.template > ./src/environments/environment.prod.ts
RUN envsubst < ./src/index.html.template > ./src/index.html
RUN envsubst < ./webpack.config.js.template > ./webpack.config.js
RUN envsubst '$$PUBLIC_BASE_PATH' < ./webpack.config.js.template > ./webpack.config.js
RUN if [ "${ENVIRONMENT}" = "development" ]; then \
npm run build -- --configuration=docker-dev --base-href=${PUBLIC_BASE_PATH}viewer/; \
else \
Expand Down
147 changes: 135 additions & 12 deletions front/viewer/webpack.config.js.template
Original file line number Diff line number Diff line change
@@ -1,28 +1,151 @@
const webpack = require('webpack');
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');

const apiSitnaSource = 'node_modules/api-sitna';
const apiSitnaDestiny = '${PUBLIC_BASE_PATH}viewer/assets/js/api-sitna';
const path = require("path");
const apiSitnaDestiny = 'assets/js/api-sitna';

// Angular 22 always passes supportedBrowsers into its Babel loader, so matched
// dependencies are transformed. jszip/util crash that path under optimize.
const skipAngularBabel = /[\\/]node_modules[\\/](?:jszip|util)[\\/]/;

function ruleUsesAngularBabel(rule) {
const entries = [];
if (typeof rule.loader === 'string') {
entries.push(rule.loader);
}
if (Array.isArray(rule.use)) {
for (const use of rule.use) {
if (typeof use === 'string') {
entries.push(use);
} else if (use && typeof use.loader === 'string') {
entries.push(use.loader);
}
}
}
return entries.some(
(loader) =>
loader.includes(`${path.sep}babel${path.sep}webpack-loader`) ||
loader.includes('@angular-devkit/build-angular/src/tools/babel')
);
}

function appendExclude(rule, excludeRe) {
const existing = rule.exclude;
if (!existing) {
rule.exclude = [excludeRe];
return;
}
if (Array.isArray(existing)) {
if (!existing.includes(excludeRe)) {
rule.exclude = [...existing, excludeRe];
}
return;
}
rule.exclude = [existing, excludeRe];
}

function excludeFromAngularBabel(rule) {
if (!rule || typeof rule !== 'object') {
return;
}
if (Array.isArray(rule.oneOf)) {
rule.oneOf.forEach(excludeFromAngularBabel);
}
if (Array.isArray(rule.rules)) {
rule.rules.forEach(excludeFromAngularBabel);
}
if (ruleUsesAngularBabel(rule)) {
appendExclude(rule, skipAngularBabel);
}
}

module.exports = {
module.exports = (config) => {
config.output = {
...config.output,
publicPath: '${PUBLIC_BASE_PATH}viewer/'
};

resolve: {
// Evita errores del tipo "Module not found" durante el empaquetamiento
const existingProxy = config.devServer && config.devServer.proxy;
const proxyEntries = Array.isArray(existingProxy)
? [...existingProxy]
: existingProxy
? Object.entries(existingProxy).map(([context, options]) => ({
context: [context],
...options
}))
: [];
proxyEntries.push({
context: ['/catastro-inspire'],
target: 'https://ovc.catastro.meh.es',
changeOrigin: true,
pathRewrite: { '^/catastro-inspire': '/INSPIRE' },
secure: false
});
config.devServer = {
...config.devServer,
hot: false,
liveReload: false,
client: false,
proxy: proxyEntries
};

config.resolve = {
...config.resolve,
fallback: {
...(config.resolve && config.resolve.fallback),
assert: false,
util: false,
process: require.resolve('process/browser')
},
alias: {
...(config.resolve && config.resolve.alias),
'@spz-loader/core': path.resolve(__dirname, 'src/shims/empty-spz-loader.js')
}
};

const assetsPath = path.resolve(__dirname, 'src/assets');
const previousNoParse = config.module && config.module.noParse;
config.module = {
...config.module,
noParse: (filePath) => {
if (skipAngularBabel.test(filePath)) {
return true;
}
if (filePath.includes(assetsPath) && filePath.endsWith('.js')) {
return true;
}
if (typeof previousNoParse === 'function') {
return previousNoParse(filePath);
}
if (Array.isArray(previousNoParse)) {
return previousNoParse.some((re) =>
re instanceof RegExp ? re.test(filePath) : false
);
}
if (previousNoParse instanceof RegExp) {
return previousNoParse.test(filePath);
}
return false;
}
},
};

if (Array.isArray(config.module.rules)) {
config.module.rules.forEach(excludeFromAngularBabel);
}

plugins: [
// Procesado de polyfill
config.plugins = [
...(config.plugins || []),
new webpack.ProvidePlugin({
process: 'process/browser'
}),

// Define la ruta base de la API SITNA para la carga de recursos
new CopyWebpackPlugin({
patterns: [{ from: apiSitnaSource, to: apiSitnaDestiny }]
}),
new webpack.DefinePlugin({
SITNA_BASE_URL: JSON.stringify(apiSitnaDestiny)
SITNA_BASE_URL: JSON.stringify('${PUBLIC_BASE_PATH}viewer/assets/js/api-sitna/')
})
],
];

return config;
};
Loading