วิธีและเหตุผลในการตั้งค่าบิลด์ที่ให้คุณเขียนส่วนประกอบ .vue ใน TypeScript

โอเค อาจจะไม่ใช่ทั้งวัน แต่ก็ยังใช้เวลานานเกินไปในการตั้งค่าเครื่องมือสำหรับโปรเจ็กต์ใหม่ และบางสิ่งยังยากเกินไปสำหรับรสนิยมของฉัน ไม่ใช่สิ่งที่ 'ยาก' ที่ดีเหมือนกับ ความท้าทาย เหมือนน่าเบื่อเลย ใช่ ฉันกำลังพูดถึง "webpack", "TypeScript" และไฟล์ .vue ฉันอยากจะแสดงให้เห็นว่าฉันทำอะไรลงไป และทำไมฉันถึงยังทำแบบนั้นอยู่

หากคุณกำลังมองหาการแก้ไข TypeScript อย่างรวดเร็ว นั่นค่อนข้างง่าย คว้า "webpack-blocks" และตั้งค่าภายใน 5 นาที สิ่งที่ฉันพยายามทำคือแปลกใหม่มากกว่านี้ถ้าคุณต้องการ ฉันต้องการใช้ Vue และโดยเฉพาะไฟล์ .vue กับ TypeScript ข้อมูลกระจัดกระจายไปทั่วเว็บ ดังนั้นฉันจึงคิดว่าการรวบรวมข้อมูลทั้งหมดไว้ที่นี่เพื่อใช้อ้างอิงอย่างรวดเร็วอาจไม่ใช่ความคิดที่ดี

8 พฤษภาคม 2017 อัปเดต:ตั้งแต่ฉันเขียนบทความนี้ webpack-blocks 1.0.0 ก็เกือบจะวางจำหน่ายแล้ว มีให้บริการแล้วบน NPM ดังนั้นฉันจึงใช้เวลาในการเผยแพร่โค้ดบางส่วนที่กล่าวถึงในบทความนี้ ฉันจะเผยแพร่โพสต์แยกต่างหากซึ่งสรุปการเปลี่ยนแปลงเมื่อเทียบกับบทความต้นฉบับ

ก่อนที่เราจะเริ่มต้น ลืมสิ่งที่คุณรู้เกี่ยวกับวิธีเขียนส่วนประกอบ Vue หากคุณต้องการใช้ไฟล์ .vue ด้วย TypeScript คุณต้องเขียนโค้ดด้วยวิธี TypeScript แน่นอนคุณสามารถเขียนโค้ดด้วยวิธีเก่าได้ แต่คุณจะไม่ได้รับประโยชน์จากการตรวจสอบประเภท ดังนั้นจึงเป็นการเสียเวลาของคุณ คุณได้รับคำเตือน

ทำไมต้องเป็นไฟล์ .vue

ก่อนอื่น ให้ฉันอธิบายว่าทำไมฉันถึงต้องการให้ .vue ไฟล์เริ่มต้นด้วย (ในกรณีที่คุณไม่รู้ว่ามันคืออะไร ดูที่ ที่นี่) แพ็คเกจไฟล์เดียวหลายภาษาเหล่านี้ไม่ได้เป็นเพียงเครื่องมือสำหรับการจัดกลุ่มสิ่งที่อาจเป็นชุดของไฟล์หลวม ๆ เข้าด้วยกัน ไม่ พวกเขามีข้อดีของตัวเองที่เป็นมากกว่าการรวมโค้ดเข้าด้วยกัน

ตัวอย่างเช่น เทมเพลต HTML ถูกเข้ารหัสด้วย HTML ดังนั้นคุณจึงได้รับการสนับสนุนการเน้นไวยากรณ์ การเติมข้อมูลอัตโนมัติแบบรับรู้บริบท และ/หรือการสนับสนุน emmet นักพัฒนา JavaScript ที่ยอดเยี่ยมนั้นมีไม่มากนัก ดังนั้นการเขียนโค้ด HTML ธรรมดา (ซึ่งตรงข้ามกับ JSX และที่แย่กว่านั้นคือ hyperscript) จึงสามารถไปได้ไกล ใช่ ฉันทราบดีว่ามีเรื่องราวเกี่ยวกับนักออกแบบและมือใหม่ที่เลือกใช้ไฮเปอร์สคริปต์และสิ่งที่คล้ายคลึงกัน และจริงๆ แล้วชอบมัน แต่คุณต้องจำไว้ว่าแม้แต่นักพัฒนา JavaScript ที่มีประสบการณ์ก็ไม่ยอมแพ้โดยไม่ต้องทะเลาะกันในบางครั้ง

ประการที่สอง CSS ที่กำหนดขอบเขต หากคุณยังคงคิดว่า BEM มีตำแหน่งในเฟรมเวิร์กส่วนหน้าที่มีเครื่องมืออย่างเหมาะสม แสดงว่าคุณเข้าใจถึงความสำคัญและความท้าทายของ CSS ที่ได้รับการจัดการอย่างดี คุณอาจถูกเตะออกจาก CSS ที่กำหนดขอบเขต ฉันจะไม่พยายามขาย CSS ที่กำหนดขอบเขตให้คุณ มันเหมือนกับยาเสพติด: มันขายตัวมันเอง แค่ลองดู. ฉันท้าคุณ.

ทั้งหมดนี้ และความจริงที่ว่าฉันกำลังจัดการกับไฟล์เดียวแทนที่จะเป็นสามหรือสี่ไฟล์ ถือเป็นข้อโต้แย้งที่ดีพอที่จะใช้เวลาเพิ่มเติมในการรับไฟล์ .vue ที่ทำงานกับ TypeScript

ทำไมต้องพิมพ์สคริปต์?

นี่คือสิ่งที่คุณต้องมาถึงด้วยตัวเองหากเคย ในอดีตผู้คนเคยใช้ JavaScript ที่ไม่ได้พิมพ์ และมันใช้งานได้จริง อันที่จริง ฉันกำลังพยายามตัดสินใจระหว่าง TypeScript และ "LiveScript" ซึ่งเป็น "CoffeeScript" เวอร์ชันที่ยังไม่ได้พิมพ์ ซึ่งมีไวยากรณ์ที่สั้นและค่อนข้างแปลก

ท้ายที่สุดแล้ว มันขึ้นอยู่กับประสิทธิภาพการทำงาน LiveScript มีไวยากรณ์และทางลัดที่ละเอียดน้อยกว่าสำหรับหลายสิ่งที่ฉันใช้ในแต่ละวัน TypeScript จะตรวจจับข้อผิดพลาดในการเขียนโค้ดมากมายที่ฉันอาจทำ และอาจให้ข้อมูลเพิ่มเติมเกี่ยวกับโค้ดที่ทำให้การทำงานกับไลบรารีและเฟรมเวิร์กที่ไม่คุ้นเคยง่ายขึ้นมาก ฉันเลือกอย่างหลังมากกว่าอันแรกด้วยเหตุผลความรู้สึกโดยพลการ

หากคุณต้องขอบัญชีกราฟิกว่าการใช้ TypeScript ในการผลิตเป็นอย่างไร มี บทความดีๆ จากทีม Slack

พูดพอแล้ว มาเขียนโค้ดกันดีกว่า… หรืออาจจะไม่ใช่ก็ได้

ก่อนที่เราจะสามารถเขียนโค้ดได้ เราต้องตั้งค่าเครื่องมือก่อน

ขั้นแรก เลือก webpack-blocks นั่นเป็นวิธีที่ง่ายที่สุดในการกำหนดค่า webpack ที่ฉันรู้ ง่ายที่สุดหลังจากเพียงแค่คัดลอกและวางการกำหนดค่าที่มีอยู่ แต่คุณเข้าใจประเด็นของฉัน

ตอนนี้ webpack-blocks ไม่ รองรับไฟล์ .vue ไฟล์ทันที มีแพ็คเกจบุคคลที่สามสองแพ็คเกจที่ทำให้สามารถใช้ไฟล์ .vue ได้

การกำหนดค่า TypeScript ในตัวใน webpack-blocks ใช้ "awesome-typescript-loader" มันเป็นตัวโหลดที่ดี แต่ไม่เล่นได้ดีกับไฟล์ .vue (มันมีชื่อแปลกๆ ด้วย แต่นั่นคือปัญหาของฉัน) นอกจากแพ็คเกจสำหรับการกำหนดค่า vue-loader แล้ว เรายังต้องมีแพ็คเกจที่จะกำหนดค่า ts-loader ซึ่งมีข้อกำหนดบางประการสำหรับการทำงานกับรูปแบบคอนเทนเนอร์ เช่น .vue

npm i -D webpack-blocks-vue webpack-blocks-ts

ในที่สุดคุณก็จะได้ไฟล์แบบนี้ webpack.config.js สิ่งสำคัญที่ควรทราบ:

  • เรากำลังส่งตัวเลือก { appendTsSuffixTo: [/\.vue$/] } ไปยัง ts-loader เพราะไม่เช่นนั้นคอมไพเลอร์ TypeScript ก็ไม่ต้องการให้ความร่วมมือ สิ่งนี้ทำให้ไฟล์ .vue ถือเป็น .vue.ts เช่นเดียวกับที่คอมไพเลอร์ TypeScript ชอบ
  • เราไม่ได้ใช้บาเบล หากคุณต้องการใช้ JSX คุณอาจต้องการใช้มัน แต่ฉันไม่ต้องการ
  • เรากำลังส่ง { esModule: true } ไปยัง vue-loader ตัวเลือกนี้บอกให้โหลดเดอร์ปล่อยโมดูล ES2015 แทนที่จะเป็นโมดูล CommonJS เห็นได้ชัดว่า TypeScript ไม่ชอบโมดูล CommonJS

คุณต้องแจ้งให้ TypeScript ทราบว่าไฟล์ .vue คืออะไร และจะจัดการกับไฟล์เหล่านี้อย่างไร เพื่อจุดประสงค์นี้ เราจึงเพิ่ม vue.d.ts file ลงในแผนผังต้นทาง คำจำกัดความนี้จะบอก TypeScript ว่าการส่งออกเริ่มต้นจากไฟล์ .vue จะเป็นอย่างไร

ตอนนี้เราเขียนโค้ดได้ไหม?

ใช่เราทำได้ ตามที่ฉันได้กล่าวไว้ในบทนำ คุณไม่สามารถเขียนโค้ดเหมือนแต่ก่อนและคาดหวังว่าสิ่งต่างๆ จะได้ผลได้ การเข้ารหัสไฟล์ .vue สำหรับ TypeScript ต้องใช้แนวทางที่แตกต่างออกไป แต่อย่ากลัวเลย ไวยากรณ์ทางเลือกนั้นสมเหตุสมผลมาก และในความคิดของฉัน ทำให้โค้ดอ่านง่ายขึ้นมาก (ไม่ต้องพูดถึงประเภทการตรวจสอบความดี)

ก่อนอื่นคุณจะต้องเพิ่มการพึ่งพาเพิ่มเติม: vue-property-decorator

ส่วนประกอบของคุณจะมีลักษณะดังนี้:

<template>
  <div class="hello">Hello, {{ name }}</div>
</template>
<script lang="ts">
import Vue from 'vue'
import { Component, Prop } from 'vue-property-decorator'
@Component
export default class Hello extends Vue {
  @Prop
  name: string
}
</script>
<style scoped>
.hello {
  font-size: 200px;
  font-family: sans-serif;
}
</style>

ฉันจะไม่ลงรายละเอียดมากเกินไปที่นี่ เพราะทั้ง vue-property-decorator และ vue-class-component ซึ่งใช้เป็นหลัก ได้รับการจัดทำเอกสารไว้ค่อนข้างดีและตรงไปตรงมาในการใช้งาน

ประเด็นหลักที่ต้องระวังก็คือสไตล์นี้จะขจัดเวทมนตร์/แผงหม้อน้ำออกไปจำนวนมาก (หรือซ่อนมันไว้อยู่แล้ว) แทนที่จะกำหนดตัวเฝ้าดูและวิธีการภายใต้วัตถุที่ซ้อนกันแล้วใช้ this เพื่อหมายถึงวัตถุภายนอก (ซึ่งเดินทางโดยตัวตรวจสอบประเภทของ TypeScript อย่างถูกต้อง) วิธีการทั้งหมดจะถูกกำหนดไว้บนวัตถุที่ this ถูกผูกไว้ มันทำให้ทุกอย่างเข้าใจและปฏิบัติตามได้ง่ายขึ้นเล็กน้อย ทำให้สิ่งต่าง ๆ ใกล้เคียงกับการทำงานของ JavaScript มากขึ้นเล็กน้อย

คุณจะพบตัวอย่างแบบเต็มได้ใน vue-ts-sandbox repo ของฉัน

โปรดทราบว่าแม้ว่าคุณจะไม่สนใจ TypeScript แต่คุณสามารถใช้มัณฑนากรเหล่านี้กับ Babel ได้

มันคุ้มค่าไหม?

อย่างที่คุณเห็น มันยุ่งยากมากในการทำงาน แม้ว่าในปัจจุบัน เมื่อมองย้อนกลับไปด้วยประโยชน์ของความรู้สะสมที่บันทึกไว้แล้ว ก็ยังต้องใช้เวลาสักระยะในการตั้งค่าต่างๆ คำถามก็คือว่ามันคุ้มค่าหรือไม่

ดังที่ฉันได้กล่าวไว้ในส่วน ทำไมต้องพิมพ์สคริปต์ มันเป็นสิ่งที่คุณต้องทำด้วยตัวเอง

ฉันเชื่อว่าความยุ่งยากของคำอธิบายประกอบประเภทและการกำหนดค่าบิวด์นั้นคุ้มค่าอย่างยิ่งเมื่อตัวตรวจสอบประเภทช่วยให้คุณรู้ว่าคุณได้ส่งอาร์กิวเมนต์ที่ไม่ถูกต้อง หรือลืมกำหนดบางสิ่งให้กับคุณสมบัติ หรือประเภทการส่งคืนของฟังก์ชันบางอย่างไม่เป็นเช่นนั้น สิ่งที่คุณคิดว่ามันจะเป็น คุณได้รับความคิด การประกาศอินเทอร์เฟซอย่างชัดเจนยังช่วยให้ฉันเข้าใจฐานโค้ดดีขึ้นอีกเล็กน้อย และทำให้ฉันช้าลงมากพอที่จะหลีกเลี่ยงข้อผิดพลาดที่เร่งรีบ

ตอนนี้ต้องใช้ความพยายามพิเศษเล็กน้อยเพื่อไปให้ถึงจุดนั้น แต่ลองคิดดู: การทดสอบหน่วยต้องใช้ความพยายามพิเศษเล็กน้อย (มากกว่านี้มาก!) และไม่มีใครจะโต้แย้งว่าการทดสอบหน่วยนั้นไม่คุ้มค่า ในบรรทัดเดียวกัน นี่เป็นเพียงอีกเลเยอร์หนึ่งที่มีส่วนช่วยในเรื่องคุณภาพของโค้ด นั่นคือวิธีที่ฉันมองมันต่อไป