LoginSignup
3
4

More than 5 years have passed since last update.

Nuxt.js + TypeScript 環境に tslint を導入

Last updated at Posted at 2018-12-20

はじめに

単一ファイルコンポーネント(.vue)に tslint を導入しようと試みたところ
<script lang="ts"></script> の部分以外にも lint が適応されてしまう問題に当たってしまった。
この記事ではその解決方法を交え tslint の導入方法を記載します。typescript の導入までは他の記事を参考にしたので、そもそも typescript の導入方法が異なる方は多少わかりづらいかも知れません。

前提

  • 既に単一ファイルコンポーネントに typescript で書ける環境が整っていること。
  • typescript の導入までは下記記事を参考にしましたので、ディレクトリー構造は下記記事と同様のまま説明していきます。

  ※ 参考記事(typescriptの導入)
  create-nuxt-appで構築したNuxt2のプロジェクトにTypeScriptを入れてvuexを使えるところまで持っていく

使用するパッケージ

一応バージョンも記載しておきます

  • tslint (v5.11.0)
  • tslint-loader (v3.5.4)
  • loader-utils (1.1.0)
  • vue-parser (1.1.6)

手順

STEP1: 必要なパッケージのインストール

npmの場合
$ npm install --save-dev tslint tslint-loader loader-utils vue-parser
yarnの場合
$ yarn add --dev tslint tslint-loader loader-utils vue-parser

STEP2: tslint-loaderの修正(vue-parserを使用する)

まず tslint を導入するに当たって tslint-loader を webpack の設定へ噛ませる必要があるのですが、
tslint-loader をそのまま使用すると <script lang="ts"></script> 以外の箇所も lint が適応されてしまうので
tslint-loader 自体を少し修正します。

tslint-loader 自体は node_modules/ の中にあるので、
一旦コピーしたファイル(_tslint-loader.js)を modules/ ディレクトリーへ置きます。

tslint-loaderをコピー
$ cp node_modules/tslint-loader/index.js modules/_tslint-loader.js

node_modules/tslint-loader/formatters/ の customFormatter.js も modules/ にコピーしておく
(無いと後々エラーになるため)

formatterをコピー
$ cp node_modules/tslint-loader/formatters/customFormatter.js modules/formatters/customFormatter.js

コピーした _tslint-loader.js の下記コード部分に少し修正を加えます

modules/_tslint-loader.js(修正前)
module.exports = function(input, map) {
  this.cacheable && this.cacheable();
  var callback = this.async();

  if (!semver.satisfies(Lint.Linter.VERSION, '>=4.0.0')) {
    throw new Error('Tslint should be of version 4+');
  }

  var options = resolveOptions(this);
  lint(this, input, options);
  callback(null, input, map);
};
modules/_tslint-loader.js(修正後)
var vueParser = require('vue-parser');
//...
module.exports = function(input, map) {
  this.cacheable && this.cacheable();
  var callback = this.async();

  if (!semver.satisfies(Lint.Linter.VERSION, '>=4.0.0')) {
    throw new Error('Tslint should be of version 4+');
  }

  var options = resolveOptions(this);
  // https://github.com/wbuchwalter/tslint-loader/issues/105
  if (/<script.*lang="ts".*>([\s|\S]*)<\/script>/.test(input)) {
    const _input = vueParser.parse(input, 'script', { lang: ['ts', 'tsx'] });
    lint(this, _input, options);
  } else {
    lint(this, input, options);
  }
  callback(null, input, map);
};

STEP3: tslint-loader を webpack へ噛ませる

修正した _tslint-loader.js を webpack へ噛ませるために modules/typescript.js を修正します。

modules/typescript.js(修正前)
module.exports = 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$/]
      }
    }
    // 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 = {
          ts: "tsLoader"
        }
      }
    }
    // Add .ts extension in webpack resolve
    if (config.resolve.extensions.indexOf(".ts") === -1) {
      config.resolve.extensions.push(".ts")
    }
  })
}
modules/typescript.js(修正後)
const path = require('path');

module.exports = 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$/]
      }
    }
    const tslintLoader = {
      loader: path.resolve(__dirname, '_tslint-loader.js'),
      // tslint の linterOptions.exclude で除外ファイルを指定できますが、
      // コマンドラインから tslint を実行した場合のみ有効なので、下記で除外ファイルを指定する必要があリます
      exclude: /node_modules|\.nuxt/,
      enforce: 'pre',
      options: {
        configFile: 'tslint.json',
      }
    }
    // Add TypeScript loader
    config.module.rules.push(
      Object.assign(
        {
          test: /((client|server)\.js)|(\.tsx?)$/
        },
        tsLoader,
      )
    )
    // Add TypeScript loaders
    config.module.rules.push(
      Object.assign(
        {
          test: /((client|server)\.js)|(\.tsx?)$/
        },
        tslintLoader,
      )
    )
    // Add TypeScript loader for vue files
    for (let rule of config.module.rules) {
      if (rule.loader === "vue-loader") {
        rule.options.loaders = {
          ts: "tsLoader!tslintLoader"
        }
      }
    }
    // Add .ts extension in webpack resolve
    if (config.resolve.extensions.indexOf(".ts") === -1) {
      config.resolve.extensions.push(".ts")
    }
  })
}

STEP4: tslint.json ファイルを作成する

tslint.jsonファイルの作成
$ touch tslint.json
tslint.json(例)
{
  "defaultSeverity": "error",
  "extends": "tslint:recommended",
  "rules": {
    "no-namespace": false,
    "no-string-literal": false,
    "max-line-length": {
      "options": {"limit": 120},
      "severity": "warn"
    },
    "interface-name": [true,  "never-prefix"],
    "ordered-imports": false,
    "object-literal-sort-keys": false
  }
}

STEP5: 完了

これで一通り完了なので、Nuxtの開発環境を立ち上げてみましょう。

nuxtの開発環境立ち上げ
# yarn
$ yarn run dev
# npm
$ npm run dev

下記のように tslint が動作していれば完了です🎉
image.png

オプション

tslint は正常に動作するようになったものの、
少し見にくいのでログを見やすくするために formatter を追加します

STEP1

custom-tslint-formatters をインストールします(npm での install は割愛)

$ yarn add --dev custom-tslint-formatters

STEP2

options に formatter と formattersDirectory を追加

modules/typescript.js
    const tslintLoader = {
      loader: path.resolve(__dirname, '_tslint-loader.js'),
      // tslint の linterOptions.exclude で除外ファイルを指定できますが、
      // コマンドラインから tslint を実行した場合のみ有効なので、下記で除外ファイルを指定する必要があリます
      exclude: /node_modules|\.nuxt/,
      enforce: 'pre',
      options: {
        configFile: 'tslint.json',
        // ↓ formatter と formattersDirectory オプションを追加
        formatter: 'grouped',
        formattersDirectory: 'node_modules/custom-tslint-formatters/formatters',
      }
    }

STEP3

Nuxtの開発環境を立ち上げて確認する。
lint の error 内容が見やすくなりました🎉
image.png

最後に

何か記事に間違いなどありましたらご指摘よろしくお願いします。
参考にしたURLをまとめておきます

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4