Angular 15 'ng serve' builds app very slowly, every change is very slow

Discussão em 'Angular' iniciado por ajdin.bulut, Julho 23, 2025.

  1. ajdin.bulut

    ajdin.bulut Guest

    Im using angular v15 for my project. It's not small but not really big. I'd say medium to big. Running ng serve takes A LOT of time.

    Build at: 2025-07-23T12:23:56.259Z - Hash: 5ba2b19880727f6c - Time: 150153ms

    Making a really small change like adding console.log:

    Build at: 2025-07-23T12:28:27.654Z - Hash: be9deeddc53e7be5 - Time: 60598ms

    I mean this is just ridiculous and I have no idea what's wrong..

    I'm still using NgModules and have around 150 of them.

    this is my angular.json setting for build and serve

    "build": {
    "builder": "@angular-builders/custom-webpack:browser",
    "options": {
    "customWebpackConfig": {
    "path": "webpack.config.js"
    },
    "sourceMap": true,
    "optimization": true,
    "statsJson": true,
    "outputPath": "dist/fuse",
    "index": "src/index.html",
    "main": "src/main.ts",
    "polyfills": [
    "zone.js"
    ],
    "tsConfig": "tsconfig.app.json",
    "inlineStyleLanguage": "scss",
    "allowedCommonJsDependencies": [
    "apexcharts",
    "highlight.js",
    "crypto-js/enc-utf8",
    "crypto-js/hmac-sha256",
    "crypto-js/enc-base64",
    "flat",
    "quill",
    "lodash",
    "moment",
    "pdfmake/build/pdfmake",
    "pdfmake/build/vfs_fonts",
    "html-to-pdfmake",
    "jquery",
    "quill-image-resize-module-ts"
    ],
    "assets": [
    "src/favicon-16x16.png",
    "src/favicon-32x32.png",
    "src/web.config",
    "src/assets",
    {
    "glob": "_redirects",
    "input": "src",
    "output": "/"
    }
    ],
    "stylePreprocessorOptions": {
    "includePaths": [
    "src/@fuse/styles"
    ]
    },
    "styles": [
    "node_modules/@fortawesome/fontawesome-free/css/all.min.css",
    "node_modules/angular-calendar/css/angular-calendar.css",
    "node_modules/flatpickr/dist/flatpickr.css",
    "node_modules/slick-carousel/slick/slick.css",
    "node_modules/slick-carousel/slick/slick-theme.css",
    "src/@fuse/styles/tailwind.scss",
    "src/@fuse/styles/themes.scss",
    "src/styles/vendors.scss",
    "src/@fuse/styles/main.scss",
    "src/styles/styles.scss",
    "src/styles/tailwind.scss"
    ],
    "scripts": [
    "node_modules/jquery/dist/jquery.min.js",
    "node_modules/slick-carousel/slick/slick.min.js"
    ]
    },
    "configurations": {
    "production": {
    "customWebpackConfig": {
    "path": "webpack.config.js"
    },
    "outputPath": "dist/production",
    "fileReplacements": [
    {
    "replace": "src/environments/environment.ts",
    "with": "src/environments/environment.prod.ts"
    }
    ],
    "budgets": [
    {
    "type": "initial",
    "maximumWarning": "3mb",
    "maximumError": "10mb"
    },
    {
    "type": "anyComponentStyle",
    "maximumWarning": "75kb",
    "maximumError": "90kb"
    }
    ],
    "outputHashing": "all",
    "sourceMap": false
    },
    "staging": {
    "outputPath": "dist/staging",
    "fileReplacements": [
    {
    "replace": "src/environments/environment.ts",
    "with": "src/environments/environment.staging.ts"
    }
    ],
    "budgets": [
    {
    "type": "initial",
    "maximumWarning": "3mb",
    "maximumError": "10mb"
    },
    {
    "type": "anyComponentStyle",
    "maximumWarning": "75kb",
    "maximumError": "90kb"
    }
    ],
    "outputHashing": "all",
    "sourceMap": false
    },
    "development": {
    "buildOptimizer": true,
    "optimization": true,
    "vendorChunk": true,
    "extractLicenses": false,
    "sourceMap": true,
    "namedChunks": true
    }
    },
    "defaultConfiguration": "production"
    },
    "serve": {
    "builder": "@angular-builders/custom-webpack:dev-server",
    "options": {
    "browserTarget": "fuse:build"
    },
    "configurations": {
    "production": {
    "browserTarget": "fuse:build:production"
    },
    "development": {
    "browserTarget": "fuse:build:development",
    "hmr": true
    }
    },
    "defaultConfiguration": "development"
    },
    "extract-i18n": {
    "builder": "@angular-devkit/build-angular:extract-i18n",
    "options": {
    "browserTarget": "fuse:build"
    }
    },


    tailwind.config.js:


    const path = require("path");
    const colors = require("tailwindcss/colors");
    const defaultTheme = require("tailwindcss/defaultTheme");
    const generatePalette = require(path.resolve(
    __dirname,
    "src/@fuse/tailwind/utils/generate-palette"
    ));

    /**
    * Custom palettes
    *
    * Uses the generatePalette helper method to generate
    * Tailwind-like color palettes automatically
    */
    const customPalettes = {
    brand: generatePalette("#2196F3"),
    };

    /**
    * Themes
    */
    const themes = {
    // Default theme is required for theming system to work correctly!
    default: {
    primary: {
    ...colors.indigo,
    DEFAULT: colors.indigo[600],
    },
    accent: {
    ...colors.slate,
    DEFAULT: colors.slate[800],
    },
    warn: {
    ...colors.red,
    DEFAULT: colors.red[600],
    },
    "on-warn": {
    500: colors.red["50"],
    },
    },
    // Rest of the themes will use the 'default' as the base
    // theme and will extend it with their given configuration.
    brand: {
    primary: customPalettes.brand,
    },
    teal: {
    primary: {
    ...colors.teal,
    DEFAULT: colors.teal[600],
    },
    },
    rose: {
    primary: colors.rose,
    },
    purple: {
    primary: {
    ...colors.purple,
    DEFAULT: colors.purple[600],
    },
    },
    amber: {
    primary: colors.amber,
    },
    };

    /**
    * Tailwind configuration
    */
    const config = {
    darkMode: "class",
    content: ["./src/**/*.{html,scss,ts}", "./node_modules/flowbite/**/*.js"],
    important: true,
    theme: {
    fontSize: {
    xs: "0.625rem",
    sm: "0.75rem",
    md: "0.8125rem",
    base: "0.875rem",
    lg: "1rem",
    xl: "1.125rem",
    "2xl": "1.25rem",
    "3xl": "1.5rem",
    "4xl": "2rem",
    "5xl": "2.25rem",
    "6xl": "2.5rem",
    "7xl": "3rem",
    "8xl": "4rem",
    "9xl": "6rem",
    "10xl": "8rem",
    },
    screens: {
    sm: "600px",
    md: "960px",
    lg: "1280px",
    xl: "1440px",
    },
    extend: {
    gridTemplateColumns: {
    '5': 'repeat(5, minmax(0, 1fr))',
    },
    animation: {
    "spin-slow": "spin 3s linear infinite",
    },
    colors: {
    gray: colors.slate,
    'chat-message-blue': '#57E6FF',
    'primary-color': '#3C9ECF',
    'secondary-color': '#e3f4fb',
    'orange-color': '#ff8600',
    'title-color': '#90D5F7'
    },
    flex: {
    0: "0 0 auto",
    },
    fontFamily: {
    sans: `"Inter var", ${defaultTheme.fontFamily.sans.join(",")}`,
    mono: `"IBM Plex Mono", ${defaultTheme.fontFamily.mono.join(
    ","
    )}`,
    },
    opacity: {
    12: "0.12",
    38: "0.38",
    87: "0.87",
    },
    rotate: {
    "-270": "270deg",
    15: "15deg",
    30: "30deg",
    60: "60deg",
    270: "270deg",
    },
    scale: {
    "-1": "-1",
    },
    zIndex: {
    "-1": -1,
    49: 49,
    60: 60,
    70: 70,
    80: 80,
    90: 90,
    99: 99,
    999: 999,
    9999: 9999,
    99999: 99999,
    },
    spacing: {
    13: "3.25rem",
    15: "3.75rem",
    18: "4.5rem",
    22: "5.5rem",
    26: "6.5rem",
    30: "7.5rem",
    50: "12.5rem",
    90: "22.5rem",

    // Bigger values
    100: "25rem",
    120: "30rem",
    128: "32rem",
    140: "35rem",
    160: "40rem",
    180: "45rem",
    192: "48rem",
    200: "50rem",
    240: "60rem",
    256: "64rem",
    280: "70rem",
    320: "80rem",
    360: "90rem",
    400: "100rem",
    480: "120rem",

    // Fractional values
    "1/2": "50%",
    "1/3": "33.333333%",
    "2/3": "66.666667%",
    "1/4": "25%",
    "2/4": "50%",
    "3/4": "75%",
    },
    minHeight: ({ theme }) => ({
    ...theme("spacing"),
    }),
    maxHeight: {
    none: "none",
    },
    minWidth: ({ theme }) => ({
    ...theme("spacing"),
    screen: "100vw",
    }),
    maxWidth: ({ theme }) => ({
    ...theme("spacing"),
    screen: "100vw",
    }),
    transitionDuration: {
    400: "400ms",
    },
    transitionTimingFunction: {
    drawer: "cubic-bezier(0.25, 0.8, 0.25, 1)",
    },

    // @tailwindcss/typography
    typography: ({ theme }) => ({
    DEFAULT: {
    css: {
    color: "var(--fuse-text-default)",
    '[class~="lead"]': {
    color: "var(--fuse-text-secondary)",
    },
    a: {
    color: "var(--fuse-primary-500)",
    },
    strong: {
    color: "var(--fuse-text-default)",
    },
    "ol > li::before": {
    color: "var(--fuse-text-secondary)",
    },
    "ul > li::before": {
    backgroundColor: "var(--fuse-text-hint)",
    },
    hr: {
    borderColor: "var(--fuse-border)",
    },
    blockquote: {
    color: "var(--fuse-text-default)",
    borderLeftColor: "var(--fuse-border)",
    },
    h1: {
    color: "var(--fuse-text-default)",
    },
    h2: {
    color: "var(--fuse-text-default)",
    },
    h3: {
    color: "var(--fuse-text-default)",
    },
    h4: {
    color: "var(--fuse-text-default)",
    },
    "figure figcaption": {
    color: "var(--fuse-text-secondary)",
    },
    code: {
    color: "var(--fuse-text-default)",
    fontWeight: "500",
    },
    "a code": {
    color: "var(--fuse-primary)",
    },
    pre: {
    color: theme("colors.white"),
    backgroundColor: theme("colors.gray.800"),
    },
    thead: {
    color: "var(--fuse-text-default)",
    borderBottomColor: "var(--fuse-border)",
    },
    "tbody tr": {
    borderBottomColor: "var(--fuse-border)",
    },
    'ol[type="A" s]': false,
    'ol[type="a" s]': false,
    'ol[type="I" s]': false,
    'ol[type="i" s]': false,
    },
    },
    sm: {
    css: {
    code: {
    fontSize: "1em",
    },
    pre: {
    fontSize: "1em",
    },
    table: {
    fontSize: "1em",
    },
    },
    },
    }),

    },
    },
    corePlugins: {
    appearance: false,
    container: false,
    float: false,
    clear: false,
    placeholderColor: false,
    placeholderOpacity: false,
    verticalAlign: false,
    },
    plugins: [
    // Fuse - Tailwind plugins
    require(path.resolve(
    __dirname,
    "src/@fuse/tailwind/plugins/utilities"
    )),
    require(path.resolve(
    __dirname,
    "src/@fuse/tailwind/plugins/icon-size"
    )),
    require(path.resolve(__dirname, "src/@fuse/tailwind/plugins/theming"))({
    themes,
    }),
    require("flowbite/plugin"),

    // Other third party and/or custom plugins
    require("@tailwindcss/typography")({ modifiers: ["sm", "lg"] }),
    require("@tailwindcss/line-clamp"),
    ],
    };

    module.exports = config;

    package.json:


    {
    "name": "fuse-angular",
    "version": "17.0.1",
    "description": "Fuse - Angular Admin Template and Starter Project",
    "author": "https://themeforest.net/user/srcn",
    "license": "https://themeforest.net/licenses/standard",
    "private": true,
    "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "start:prod": "ng serve --configuration production",
    "build": "ng build",
    "build:prod": "ng build --configuration production",
    "build:staging": "ng build --configuration staging",
    "build:stats": "ng build --stats-json",
    "analyze": "webpack-bundle-analyzer dist/fuse/stats.json",
    "watch": "ng build --watch --configuration development",
    "test": "ng test",
    "lint": "ng lint",
    "explore": "source-map-explorer dist/**/*.js"
    },
    "dependencies": {
    "@angular-eslint/schematics": "^18.3.0",
    "@angular-material-components/datetime-picker": "^16.0.1",
    "@angular/animations": "15.0.0",
    "@angular/cdk": "15.0.0",
    "@angular/common": "15.0.0",
    "@angular/compiler": "15.0.0",
    "@angular/core": "15.0.0",
    "@angular/forms": "15.0.0",
    "@angular/material": "15.0.0",
    "@angular/material-luxon-adapter": "15.0.0",
    "@angular/material-moment-adapter": "^18.0.0",
    "@angular/platform-browser": "15.0.0",
    "@angular/platform-browser-dynamic": "15.0.0",
    "@angular/router": "15.0.0",
    "@fortawesome/fontawesome-free": "^6.6.0",
    "@microsoft/signalr": "^7.0.2",
    "@ng-bootstrap/ng-bootstrap": "^14.2.0",
    "@ngneat/transloco": "4.1.1",
    "@ngx-translate/core": "^14.0.0",
    "@ngx-translate/http-loader": "^8.0.0",
    "@ngxs/devtools-plugin": "^3.8.2",
    "@ngxs/storage-plugin": "^3.8.2",
    "@ngxs/store": "^3.8.2",
    "@popperjs/core": "^2.11.8",
    "angular-calendar": "^0.31.0",
    "apexcharts": "^3.53.0",
    "bootstrap": "^5.3.2",
    "crypto-js": "^4.2.0",
    "date-fns": "^2.30.0",
    "flatpickr": "^4.6.13",
    "flowbite": "^2.2.1",
    "html-to-pdfmake": "^2.5.13",
    "jquery": "^3.7.1",
    "jwt-decode": "^3.1.2",
    "lodash-es": "4.17.21",
    "luxon": "3.1.0",
    "moment": "^2.30.1",
    "ng-apexcharts": "1.7.4",
    "ng-recaptcha": "^13.2.1",
    "ngx-cookie-service": "^18.0.0",
    "ngx-image-cropper": "^6.3.2",
    "ngx-mat-select-search": "^7.0.7",
    "ngx-mat-timepicker": "^18.0.0",
    "ngx-material-file-input": "^4.0.0",
    "ngx-quill": "^20.0.1",
    "ngx-slick-carousel": "^17.0.0",
    "ngx-spinner": "^15.0.1",
    "ngx-toastr": "^16.0.1",
    "ngxs-reset-plugin": "^3.0.0",
    "pdfmake": "^0.2.20",
    "perfect-scrollbar": "1.5.5",
    "quill": "1.3.7",
    "quill-image-resize-module-ts": "^3.0.3",
    "rxjs": "7.5.7",
    "slick-carousel": "^1.8.1",
    "zone.js": "0.12.0"
    },
    "devDependencies": {
    "@angular-builders/custom-webpack": "^15.0.0",
    "@angular-devkit/build-angular": "15.0.0",
    "@angular-devkit/core": "^18.2.5",
    "@angular-eslint/eslint-plugin": "15.2.1",
    "@angular-eslint/eslint-plugin-template": "15.2.1",
    "@angular/cli": "15.0.0",
    "@angular/compiler-cli": "15.0.0",
    "@angular/localize": "15.0.0",
    "@tailwindcss/line-clamp": "0.4.2",
    "@tailwindcss/typography": "0.5.8",
    "@types/crypto-js": "3.1.47",
    "@types/highlight.js": "10.1.0",
    "@types/jasmine": "4.3.0",
    "@types/jquery": "^3.5.32",
    "@types/lodash": "4.14.189",
    "@types/lodash-es": "4.17.6",
    "@types/luxon": "3.1.0",
    "@types/pdfmake": "^0.2.11",
    "@types/slick-carousel": "^1.6.40",
    "@typescript-eslint/eslint-plugin": "^5.48.2",
    "@typescript-eslint/parser": "^5.48.2",
    "chroma-js": "2.4.2",
    "eslint": "^8.57.0",
    "jasmine-core": "4.5.0",
    "karma": "6.4.1",
    "karma-chrome-launcher": "3.1.1",
    "karma-coverage": "2.2.0",
    "karma-jasmine": "5.1.0",
    "karma-jasmine-html-reporter": "2.0.0",
    "lodash": "^4.17.21",
    "postcss": "8.4.19",
    "raw-loader": "^2.0.0",
    "tailwindcss": "3.2.4",
    "typescript": "4.8.4",
    "webpack-bundle-analyzer": "^4.10.2"
    }
    }

    I also ran npx webpack-bundle-analyzer dist/fuse/stats.json (i know about report-generator.service.ts but i need that one as well as pdf and vfs stuff): [​IMG]

    Continue reading...

Compartilhe esta Página