vue.js - Extremt långa byggetider för en medelstor app (120+ sekunder) med TypeScript (Vue-Loader och TS-Loader)


Jag använder Nuxt 2 med TypeScript och alla de senaste beroende versionerna.

Jag har en medelstor app och kompileringstiden är alldeles för långsam.

Min PC-specifikationer: Ryzen 7 2700X (8 kärnor/16 trådar) 16 GB DDR4 3000MHZ NVM-SSD

Klientkompilering tar ~72 sekunder. Serverkompilering tar ~55 sekunder.

Min package.json

{
  "name": "nuxt",
  "version": "1.0.0",
  "private": true,
  "dependencies": {
    "@fortawesome/fontawesome-svg-core": "^1.2.8",
    "@fortawesome/free-brands-svg-icons": "^5.5.0",
    "@fortawesome/free-solid-svg-icons": "^5.5.0",
    "@fortawesome/vue-fontawesome": "^0.1.2",
    "@nuxtjs/axios": "^5.3.4",
    "@types/lodash": "^4.14.117",
    "bulma": "^0.7.2",
    "lodash": "^4.17.11",
    "nuxt": "^2.2.0",
    "nuxt-buefy": "^0.3.1",
    "nuxt-class-component": "^1.2.1",
    "nuxt-fontawesome": "^0.3.0",
    "nuxt-property-decorator": "^1.2.0",
    "v-lazy-image": "^1.2.2",
    "vue-infinite-scroll": "^2.0.2",
    "vue-moment": "^4.0.0",
    "vue-multiselect": "^2.1.3",
    "vue-recaptcha": "^1.1.1",
    "vue2-leaflet": "^1.1.1",
    "vue2-leaflet-markercluster": "^2.0.0",
    "vue2-scrollspy": "^2.3.1",
    "vuex-class": "^0.3.0"
  },
  "scripts": {
    "dev": "nuxt",
    "build": "nuxt build",
    "start": "nuxt start",
    "generate": "nuxt generate"
  },
  "devDependencies": {
    "@types/node": "^10.12.2",
    "babel-plugin-transform-class-properties": "^6.24.1",
    "babel-plugin-transform-decorators-legacy": "^1.3.5",
    "node-sass": "^4.9.4",
    "sass-loader": "^7.1.0",
    "ts-loader": "5.3.0",
    "typescript": "^3.1.6"
  }
}

Nuxt.config.js

import parseArgs from "minimist";

// https://github.com/buefy/buefy/issues/1052
global.File = typeof window === 'undefined' ? Object : window.File;

const argv = parseArgs(process.argv.slice(2), {
    alias: {
        H: "hostname",
        p: "port"
    },
    string: ["H"],
    unknown: parameter => false
});

const port =
    argv.port ||
    process.env.PORT ||
    process.env.npm_package_config_nuxt_port ||
    "3000";
const host =
    argv.hostname ||
    process.env.HOST ||
    process.env.npm_package_config_nuxt_host ||
    "localhost";

export const env = {
    baseUrl: process.env.BASE_URL || `http://${host}:${port}`
};
export const head = {
    title: "Conference Finder",
    meta: [
        {charset: "utf-8"},
        {
            name: "viewport",
            content: "width=device-width, initial-scale=1"
        },
        {
            hid: "description",
            name: "description",
            content: "Nuxt.js project"
        }
    ],
    link: [
        {
            rel: "icon",
            type: "image/x-icon",
            href: "/favicon.ico"
        }
    ],
    script: [
        {src: 'https://www.google.com/recaptcha/api.js?onload=vueRecaptchaApiLoaded&render=explicit'}
    ]
};

/*
** Customize the progress-bar color
*/
export const loading = {color: "#3B8070"};

/*
** Build configuration
*/
export const css = [
    {src: "~/assets/css/main.scss", lang: 'scss'},
    {src: 'leaflet/dist/leaflet.css', lang: 'css'},
    {src: 'leaflet.markercluster/dist/MarkerCluster.css', lang: 'css'},
    {src: 'leaflet.markercluster/dist/MarkerCluster.Default.css', lang: 'css'},
    {src: 'vue-multiselect/dist/vue-multiselect.min.css', lang: 'css'}
];

export const build = {
    build: {
        babel: {
            plugins: ['transform-decorators-legacy', 'transform-class-properties']
        },
        extend (config, { isDev, isClient }) {

        }
    }
};
export const modules = [
    "@nuxtjs/axios",
    "~/modules/typescript.js",
    'nuxt-buefy',
    ["nuxt-fontawesome", {
        imports: [
            {
                set: '@fortawesome/free-solid-svg-icons',
                icons: [
                    ...]
            }, {
                set: '@fortawesome/free-brands-svg-icons',
                icons: [
                    ...
                ]
            }
        ]
    }]];
export const axios = {};
export const plugins = [
    "~/plugins/filters.ts",
    "~/plugins/vue-moment.ts",
    {src: "~/plugins/vue-lazyimage.ts", ssr: false},
    {src: "~/plugins/vue-leaflet.ts", ssr: false},
    {src: "~/plugins/vue-infinite-scroll.ts", ssr: false},
    {src: '~/plugins/vue2-scrollspy.ts', ssr: false}
];

moduler/typescript.js

export default function() {
  // Add .ts extension for store, middleware and more
  this.nuxt.options.extensions.push("ts")
  // Extend build
  this.extendBuild(config => {
    const tsLoader = {
      loader: "ts-loader",
      options: {
        appendTsSuffixTo: [/\.vue$/]
      },
      exclude: [
        /vendor/,
        /\.nuxt/
      ]
    }
    // Add TypeScript loader
    config.module.rules.push(
      Object.assign(
        {
          test: /((client|server)\.js)|(\.tsx?)$/
        },
        tsLoader
      )
    )
    // Add TypeScript loader for vue files
    for (let rule of config.module.rules) {
      if (rule.loader === "vue-loader") {
        rule.options.loaders = rule.options.loaders || {}
        rule.options.loaders.ts = tsLoader
      }
    }
    // Add .ts extension in webpack resolve
    if (
      config.resolve.extensions.indexOf(".ts") ===
      -1
    ) {
      config.resolve.extensions.push(".ts")
    }
  })
}

Efter att ha använt --profile-flaggan på bygget, identifierade jag de långsamma laddarna:

Loader │ Förfrågningar │ Tid │ Tid/Förfrågan │ Beskrivning
ts-loader │ 190 │ 50s │ 265ms │ Ts Loader
vue-loader │ 817 │ 57s │ 70ms │ Vue Loader

Jag har ~44 .Vue-komponenter (alla med TypeScript) och 13 .Vue-sidor.

All hjälp uppskattas mycket.

Svar #1

När det gäller ts-loader bör du läsa https://github.com/TypeStrong/ts-loader#faster-builds det hjälpte våra byggtider ganska mycket.

Svar #2

Kort sagt, den troliga orsaken är att typkontroll sker på samma tråd som resten av din byggprocess. Det finns ett plugin som delar upp typkontrollen till en annan tråd. För mitt personliga projekt såg jag en 4x snabbare hastighet bara genom att göra följande:

Lägg till modulen med din favoritpakethanterare

yarn add fork-ts-checker-webpack-plugin --dev

Lägg till följande i din webpack-konfiguration:

const ForkTsCheckerWebpackPlugin=require('fork-ts-checker-webpack-plugin'); plugins: [new ForkTsCheckerWebpackPlugin()]

En exempelkonfiguration kan se ut så här:

const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');

const webpackConfig = {
  context: __dirname, // to automatically find tsconfig.json
  entry: './src/index.ts',
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        loader: 'ts-loader',
        options: {
          // disable type checker - we will use it in fork plugin
          transpileOnly: true
        }
      }
    ]
  },
  plugins: [new ForkTsCheckerWebpackPlugin()]
};

Relaterade artiklar