Nuxt2 + TypeScriptでvue-slickを使う


## TL;DR
- Nuxt2 + TypeScriptでのvue-slickの扱いと導入方法についてまとめた。
- `window is not defined`の対処法について
- TypeScriptによる`Dynamic import`のエラーの解決

## 前提
- generateして静的ページとして公開する。

## 導入
まずはパッケージをインストールする。

```bash
$ npm i -S vue-slick
$ npm i -D webpack-node-externals
```

プラグイン用のファイルを作成する。

```plugins/vue-slick.js
import Vue from "vue"
import VueSlick from "vue-slick"

Vue.use(VueSlick);
```

`nuxt.config.js`で読み込ませる。

```nuxt.config.js
...
plugins: [
 { src: '~/plugins/vue-slick', ssr: false }
]
...
```

コンポーネントを作成する。

```components/slider.vue
<template>
  <div>
    <slick ref="slick" :is="slickComp" :options="slickOptions" class="slick">
      <div><img src="~assets/images/image01.png" alt="image01"></div>
      <div><img src="~assets/images/image02.png" alt="image02"></div>
      <div><img src="~assets/images/image03.png" alt="image03"></div>
    </slick>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from "nuxt-property-decorator"
import Slick from "vue-slick"

@Component({
  components: {
    Slick
  }
})
export default class extends Vue {
  slickOptions: Object = {
    slidesToShow: 1,
    infinite: true,
    accessibility: true,
    arrows: true,
    dots: true,
    draggable: true,
    edgeFriction: 0.3,
    swipe: true
  }
}
</script>
```


## エラー
`nuxt.config.js`で`ssr: false`と指定しても`window is not defined`となる。
そのため、`vue-slick`の呼び出し方を変え、`webpack-node-externals`を導入し設定する必要がある。

```components/slider.vue
<template>
  <div>
    <slick ref="slick" :is="slickComp" :options="slickOptions" class="slick">
      <div><img src="~assets/images/image01.png" alt="image01"></div>
      <div><img src="~assets/images/image02.png" alt="image02"></div>
      <div><img src="~assets/images/image03.png" alt="image03"></div>
    </slick>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from "nuxt-property-decorator"

@Component({
  components: {
    Slick: () => import("vue-slick")
  }
})
export default class extends Vue {
  slickComp: String = ""

  mounted() {
    this.$nextTick(() => {
      this.slickComp = "Slick"
    })
  }

  slickOptions: Object = {
    slidesToShow: 1,
    infinite: true,
    accessibility: true,
    arrows: true,
    dots: true,
    draggable: true,
    edgeFriction: 0.3,
    swipe: true
  }
}
</script>
```

```nuxt.config.js
const nodeExternals = require("webpack-node-externals")
...
build: {
  extend(config, ctx) {
    if (ctx.isServer) {
      config.externals = [
        nodeExternals({
          whitelist: [/^vue-slick/]
        })
      ]
    }
  }
},
...
```

また、`tsconfig.json`の設定を` "module": "es2015"`としていたため以下のエラーが出た。

```bash
TS1323: Dynamic import is only supported when '--module' flag is 'commonjs' or 'esNext'.
Version: typescript 3.1.6
```

コンポーネント上の原因箇所は以下。

```components/slider.vue
Slick: () => import("vue-slick")
```

`tsconfig.json`の`compilerOptions`の`module`を`commonjs`か`esnext`にすることで解決できる。

```tsconfig.json
{
  "compilerOptions": {
    "module": "esnext"
  }
}

```






# 参考
[window is not defined Nuxt for vue-slick](https://stackoverflow.com/questions/53806318/window-is-not-defined-nuxt-for-vue-slick)
[staskjs/vue-slick](https://github.com/staskjs/vue-slick)
[Error when trying to use dynamic import with module: "es2015" #16675](https://github.com/Microsoft/TypeScript/issues/16675)