Я пытаюсь представить Angular 9 для устаревшей базы кода, которая работает на Java (Spring Boot, Thymeleaf) и JQuery через Webpack.
Идея состоит в том, что контентная часть сайта может быть написана в Angular вместо Thymeleaf. Это будет происходить постранично, при этом некоторые страницы будут продолжать использовать Thymeleaf / JQuery, а некоторые Angular. (Большая часть) маршрутизации будет обрабатываться SpringBoot, но я также хотел бы иметь возможность маршрутизировать через Angular.
Моя тестовая страница находится в Thymeleaf и в основном просто загружает Angular Приложение:
<div class="content-body">
<my-app>Loading...</my-app>
</div>
<script type="text/javascript" th:src="@{/static/ng-my-app.js}" defer></script>
Местоположение моего Angular приложения находится под /src/main/resources/static/ng-my-app
, также есть JQuery код в /src/main/resources/static/common
.
Мой /angular.json
:
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "src/main/resources/static",
"projects": {
"my-app": {
"projectType": "application",
"schematics": {},
"root": "src/main/resources/static/ng-my-app",
"sourceRoot": "src/main/resources/static/ng-my-app/src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/my-app",
"index": "src/main/resources/static/ng-my-app/src/index.html",
"main": "src/main/resources/static/ng-my-app/src/main.ts",
"polyfills": "src/main/resources/static/ng-my-app/src/polyfills.ts",
"tsConfig": "src/main/resources/static/ng-my-app/tsconfig.app.json",
"aot": true,
"assets": [
"src/main/resources/static/ng-my-app/src/favicon.ico",
"src/main/resources/static/ng-my-app/src/assets"
],
"styles": [
"src/main/resources/static/ng-my-app/src/styles.css"
],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/main/resources/static/ng-my-app/src/environments/environment.ts",
"with": "src/main/resources/static/ng-my-app/src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "my-app:build"
},
"configurations": {
"production": {
"browserTarget": "my-app:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "my-app:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/main/resources/static/ng-my-app/src/test.ts",
"polyfills": "src/main/resources/static/ng-my-app/src/polyfills.ts",
"tsConfig": "src/main/resources/static/ng-my-app/tsconfig.spec.json",
"karmaConfig": "src/main/resources/static/ng-my-app/karma.conf.js",
"assets": [
"src/main/resources/static/ng-my-app/src/favicon.ico",
"src/main/resources/static/ng-my-app/src/assets"
],
"styles": [
"src/main/resources/static/ng-my-app/src/styles.css"
],
"scripts": []
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"src/main/resources/static/ng-my-app/tsconfig.app.json",
"src/main/resources/static/ng-my-app/tsconfig.spec.json",
"src/main/resources/static/ng-my-app/e2e/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
}
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "src/main/resources/static/ng-my-app/e2e/protractor.conf.js",
"devServerTarget": "my-app:serve"
},
"configurations": {
"production": {
"devServerTarget": "my-app:serve:production"
}
}
}
}
}},
"defaultProject": "my-app"
}
Мой /package.json
:
{
"name": "my-project",
"private": true,
"version": "1.0.0",
"scripts": {
"ng": "ng",
"build": "webpack --config webpack.prod.js",
"build-dev": "webpack --config webpack.dev.js --progress -p",
"build-dev:watch": "webpack --config webpack.dev.js --progress --watch",
"start": "ng serve"
...
}
...
}
Мой /src/main/resources/static/ng-my-app/tsconfig.app.json
:
{
"extends": "../../../../../tsconfig.json",
"compilerOptions": {
"baseUrl": "./",
"outDir": "../../../../../out-tsc/app",
"types": [],
"paths": {
"@app/*": [ "src/app/*" ],
"@domain/*": ["src/app/domain/*"]
}
},
"files": [
"src/main.ts",
"src/polyfills.ts"
],
"include": [
"src/**/*.d.ts"
]
}
Мой /tsconfig.json
:
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"module": "esnext",
"moduleResolution": "node",
"importHelpers": true,
"target": "es2015",
"lib": [
"es2018",
"dom"
]
},
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true
}
}
Итак пока все хорошо - у меня работает базовое c Angular приложение, и я могу запустить его в режиме разработки (ng start
).
Проблема в том, что я не могу заставить его работать с существующим общим WebPack , Я пытался настроить конфигурацию WebPack, а также использовать пользовательский Angular WebPack и не могу заставить его работать. Я также не уверен, как ng build
вписывается в это. Поскольку мои попытки этого были очень грязными и их было много, я не включил измененные конфиги WebPack в этот пост.
My /webpack.config.js
:
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: {
jQueryCompA: './src/main/resources/static/common/compA/index.js',
jQueryCompB: './src/main/resources/static/common/compB/index.js'
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'target/classes/static')
},
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader'
]
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'sass-loader',
options: {
...
}
}
]
},
{
test: require.resolve('jquery'),
use: [{
loader: 'expose-loader',
options: '$'
}]
},
{
test: require.resolve('jquery.dirtyforms'),
loader: 'imports-loader?$=jquery,define=>false,exports=>false'
}
]
},
resolve: {
modules: [
path.resolve(__dirname, 'node_modules')
]
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
path: path.resolve(__dirname, 'target/classes/static')
})
],
externals: {
jquery: 'jQuery'
}
};
Для чего я пытаюсь достичь, является ли это даже правильным подходом принять общий WebPack и сказать Angular использовать собственный WebPack? Или мне нужен выделенный WebPack для Angular? Как бы я это сделал?
Я не очень разбираюсь в настройке WebPack и имею лишь ограниченный опыт установки Angular. Любые идеи и указатели в правильном направлении будут великолепны!