Meteor Tutorial: การสร้างเว็บแอปพลิเคชันแบบเรียลไทม์ด้วย Meteor
เผยแพร่แล้ว: 2022-03-11Meteor เป็นเฟรมเวิร์ก JavaScript แบบฟูลสแตกสำหรับเว็บและแอปพลิเคชันมือถือ มีมาตั้งแต่ปี 2011 และได้รับชื่อเสียงอย่างมากในหมู่นักพัฒนา Meteor ว่าเป็นโซลูชันในอุดมคติที่ใช้งานง่ายสำหรับการสร้างต้นแบบอย่างรวดเร็ว อย่างไรก็ตาม เมื่อเร็ว ๆ นี้นักพัฒนาได้ตระหนักว่า Meteor ไม่ใช่แค่การสร้างต้นแบบอีกต่อไป แต่ยังพร้อมสำหรับการพัฒนาเชิงพาณิชย์อีกด้วย ด้วยคลังแสงของแพ็คเกจที่มีให้ พื้นฐาน mongoDB/node.js ที่มั่นคงซึ่งมันอาศัย และความยืดหยุ่นในการเข้ารหัสที่มีให้ Meteor ทำให้ง่ายต่อการสร้างเว็บแอปพลิเคชันแบบเรียลไทม์ที่มีเสถียรภาพและปลอดภัย จัดการทุกอย่างตั้งแต่แอปเบราว์เซอร์ไปจนถึงเซิร์ฟเวอร์หรือฐานข้อมูล
บทแนะนำ Meteor นี้จะแนะนำคุณเกี่ยวกับการสร้างเว็บแอปพลิเคชันพื้นฐานใน Meteor ซึ่งเป็นแค็ตตาล็อกง่ายๆ ที่ให้ผู้ใช้เข้าสู่ระบบและจัดการรายชื่อหนังสือ
ทำไมต้องใช้ดาวตก? คำตอบสั้น ๆ คือ “เพราะ Meteor นั้นสนุก” ทำให้การพัฒนาเว็บแอปพลิเคชันเป็นเรื่องง่าย เรียนรู้ได้ง่าย และช่วยให้คุณมุ่งเน้นที่ฟังก์ชันการทำงานของแอปพลิเคชันของคุณได้มากกว่าการซิงค์ข้อมูลพื้นฐานและหน้าให้บริการ
นอกจากนี้ยังมีพฤติกรรมมากมายที่สร้างมาอย่างสะดวก Meteor จะทำการอัปเดตอัตโนมัติโดยอัตโนมัติ ดังนั้นการเปลี่ยนแปลงข้อมูลจึงแสดงขึ้นทันทีในหน้าต่างเบราว์เซอร์ของคุณ และแม้แต่การเปลี่ยนแปลงโค้ดของแอปพลิเคชันเองก็ถูกผลักไปยังเบราว์เซอร์และอุปกรณ์ทั้งหมดใน "เรียลไทม์" Meteor มีการชดเชยเวลาแฝงในตัว ปรับใช้ได้ง่าย และมี "แพ็คเกจ" ที่ติดตั้งง่ายซึ่งรองรับการทำงานทุกประเภท
แม้ว่าจะเป็นเฟรมเวิร์กที่ค่อนข้างใหม่ แต่สตาร์ทอัพจำนวนมากก็กำลังสร้างแอพ Meteor อยู่แล้ว รวมถึงบริการที่ค่อนข้างใหญ่ เช่น Respondly และ Telescope
การติดตั้งและนั่งร้านดาวตก
การติดตั้ง Meteor บนระบบ *nix เป็นขั้นตอนเดียว:
curl https://install.meteor.com/ | sh
แม้ว่าจะยังไม่มีการสนับสนุนอย่างเป็นทางการ แต่การแสดงตัวอย่างสำหรับ Windows ก็เข้ากันได้ดี มีข่าวลือว่าการรองรับ Windows จะมาพร้อมกับเวอร์ชัน 1.1 ซึ่งครบกำหนดในเดือนเมษายนหรือพฤษภาคม 2015 อย่างที่คุณคาดหวังจากเฟรมเวิร์กอันชาญฉลาดอย่าง Meteor การบูตแอปพลิเคชันนั้นต้องใช้คำสั่งเพียงบรรทัดเดียวในการเรียกใช้:
meteor create book-list
สิ่งนี้จะสร้างไดเร็กทอรีชื่อ "book-list" และเติมลงในนั้นด้วยต้นแบบและโค้ดที่ขึ้นต่อกัน ในการรันแอปพลิเคชัน ให้ป้อนไดเร็กทอรีที่สร้างขึ้นใหม่และดำเนินการ:
meteor
เปิด http://localhost:3000
ในเว็บเบราว์เซอร์ของคุณ แล้วคุณจะเห็นสิ่งต่อไปนี้:
คุณยังสามารถตรวจสอบ "เวอร์ชัน 0" ของแอปพลิเคชันของเราบน MeteorPad ซึ่งเป็นไซต์ที่คล้ายกับ JSFiddle สำหรับ Meteor: รายการหนังสือ: แอปเริ่มต้น
Meteor เก็บมุมมองในไฟล์ HTML หากเราเปิด “book-list.html” เราจะเห็น:
<head> <title>book-list</title> </head> <body> <h1>Welcome to Meteor!</h1> {{> hello}} </body> <template name="hello"> <button>Click Me</button> <p>You've pressed the button {{counter}} times.</p> </template>
Meteor ใช้ "Blaze" ซึ่งเป็นเครื่องมือสร้างเทมเพลตเพื่อแสดงการตอบกลับจากไฟล์ HTML เหล่านี้ เหล็กจัดฟันคู่ควรเป็นที่คุ้นเคยสำหรับผู้ที่เคยใช้ Handlebars.js (หรือเครื่องมือสร้างเทมเพลตอื่นที่คล้ายคลึงกัน) และเครื่องมือเหล่านี้ทำหน้าที่คล้ายคลึงกันที่นี่ Blaze ตรวจสอบนิพจน์ภายในวงเล็บปีกกาคู่แต่ละคู่ และแทนที่แต่ละอันด้วยค่าที่นิพจน์เหล่านี้ให้ผล
โปรแกรมตัวอย่างง่ายๆ นี้มีนิพจน์สองวงเล็บปีกกาเพียงสองนิพจน์:
อย่างแรก “{{> hello}}” บอกให้ Blaze รวมเทมเพลตที่เรียกว่า “hello” เทมเพลตนั้นถูกกำหนดไว้ที่ด้านล่างของไฟล์ ในส่วน <ชื่อเทมเพลต=”hello”>
ประการที่สอง “{{counter}}” ซับซ้อนกว่าเล็กน้อย หากต้องการดูว่าค่า "ตัวนับ" นี้มาจากไหน เราต้องเปิด "book-list.js":
if (Meteor.isClient) { // counter starts at 0 Session.setDefault('counter', 0); Template.hello.helpers({ counter: function () { return Session.get('counter'); } }); Template.hello.events({ 'click button': function () { // increment the counter when button is clicked Session.set('counter', Session.get('counter') + 1); } }); } if (Meteor.isServer) { Meteor.startup(function () { // code to run on server at startup }); }
บางสิ่งต้องการคำอธิบายที่นี่ ขั้นแรกให้แบ่งออกเป็น “if (Meteor.isClient)” และ “if (Meteor.isServer)” จำได้ว่าอุกกาบาตเป็นเฟรมเวิร์กฟูลสแต็ก ดังนั้นโค้ดที่คุณเขียนจึงทำงานได้ทั้งบนเซิร์ฟเวอร์และไคลเอนต์ เงื่อนไขเหล่านี้ทำให้เราจำกัดสิ่งนั้น: บล็อกแรกทำงานบนไคลเอนต์เท่านั้น และบล็อกที่สองทำงานบนเซิร์ฟเวอร์เท่านั้น
อย่างที่สอง มีการเรียก “Session.setDefault” ซึ่งเป็นการเริ่มต้นตัวแปรเซสชันที่เรียกว่า “ตัวนับ” ในเบราว์เซอร์ ตัวแปรเซสชันทำหน้าที่คล้ายกับ globals ใน Meteor (ทั้งในแง่ดีและร้าย) อย่างไรก็ตาม ตัวแปรเซสชันนั้นไม่แสดงใน “{{counter}}” โดยตรง นิพจน์ "ตัวนับ" นั้นเป็น "ตัวช่วย" แทน ซึ่งกำหนดไว้ในส่วน "Template.hello.helpers" ตัวช่วยนี้เพียงแค่คว้าค่าของตัวแปรเซสชันแล้วส่งคืน
โปรดทราบว่าตัวช่วยนั้น "มีปฏิกิริยา" ซึ่งหมายความว่าทุกครั้งที่ตัวแปรเซสชันเปลี่ยนแปลง Meteor จะเรียกใช้ฟังก์ชันตัวช่วยที่อ้างอิงถึงตัวแปรนี้อีกครั้งโดยอัตโนมัติ และ Blaze จะอัปเดตเบราว์เซอร์ด้วยเนื้อหาใหม่โดยอัตโนมัติ
รหัสลูกค้ายังตรวจสอบเหตุการณ์ผ่าน “Template.hello.events” เราระบุเหตุการณ์ตามประเภทเหตุการณ์และตัวเลือก (ในกรณีนี้คือ “ปุ่มคลิก”) จากนั้นบอก Meteor ว่าเหตุการณ์นั้นควรทำอย่างไร ในกรณีนี้ ตัวแปรเซสชันจะเพิ่มขึ้น ซึ่งจะเรียกใช้ฟังก์ชันตัวช่วยอีกครั้งและแสดงเนื้อหาอีกครั้ง
กำลังแสดงข้อมูลคงที่
ทั้งหมดนี้ดีและดี แต่ไม่ใช่แอปพลิเคชัน Meteor ที่เราต้องการสำหรับบทช่วยสอนนี้
มาเริ่มปรับแต่งแอปพลิเคชันนี้กันเถอะ - เราจะแสดงรายการหนังสือแบบคงที่และกำหนดรหัสตายตัว สำหรับตอนนี้ เราจะเก็บรายชื่อหนังสือไว้ในตัวแปรเซสชัน ในโค้ด "isClient" เราจะใช้ "Template.hello.rendered" เพื่อตั้งค่าตัวแปรเซสชันทันทีที่เทมเพลต bookList แสดงผล:
Template.hello.rendered = function() { Session.setDefault('books', [ {title: "To Kill a Mockingbird", author: "Harper Lee"}, {title: "1984", author: "George Orwell"}, {title: "The Lord of the Rings", author: "JRR Tolkien"}, {title: "The Catcher in the Rye", author: "JD Salinger"}, {title: "The Great Gatsby", author: "F. Scott Fitzgerald"} ]); };
จากนั้น เราส่งคืนตัวแปรเซสชันนั้นด้วยตัวช่วยใหม่ในเทมเพลต "สวัสดี":
Template.hello.helpers({ books: function () { return Session.get('books'); } });
และแสดงบนหน้าจอผ่านการแก้ไขตัวแปรในเทมเพลต "สวัสดี":
<template name="hello"> <h3>Here are your books:</h3> {{ books }} </template>
คุณสามารถตรวจสอบโค้ดนี้ได้บน Meteorpad: Book-List: Show Session Variable
สิ่งแรกที่ควรสังเกตคือเซิร์ฟเวอร์ Meteor ตรวจพบการเปลี่ยนแปลงใน codebase ของเราโดยอัตโนมัติ ผลักรหัสใหม่ไปยังไคลเอนต์ และแจ้งให้ไคลเอนต์โหลดซ้ำ แม้ว่าเราจะปรับใช้แอปพลิเคชันแล้ว เราก็สามารถปรับใช้การเปลี่ยนแปลงและอัปเดตไคลเอ็นต์ของเราโดยอัตโนมัติผ่านการพุชรหัสด่วน
จนถึงตอนนี้ นี่คือสิ่งที่เราได้รับ:
อ๊ะ เราแสดงข้อมูลไม่ถูกต้อง Blaze ได้คะแนนสำหรับความแม่นยำที่นี่ (เพราะเหตุใด มันเป็นอาร์เรย์ของวัตถุ) แต่เราจะต้องฉลาดขึ้นอีกเล็กน้อยถ้าเราต้องการแสดงรายการหนังสือของเราในลักษณะที่เป็นประโยชน์ โชคดีที่ Blaze ทำให้การทำงานกับอาร์เรย์ของข้อมูลทำได้ง่ายมากโดยใช้คำสั่ง “#each”:
<h3>Here are your books:</h3> <UL> {{#each books}} <LI><i>{{title}}</i> by {{author}}</LI> {{/each}} </UL>
ใน Blaze “#each” ทำงานคล้ายกับคำสั่ง “ng-repeat” ของ Angular โดยจะวนซ้ำผ่านโครงสร้างอาร์เรย์ ตั้งค่าบริบทปัจจุบันเป็นวัตถุปัจจุบันในอาร์เรย์ และแสดง HTML ซ้ำๆ ภายใน “{{#each …}}”. นี่คือรายชื่อหนังสือของเราในตอนนี้:
บน MeteorPad: แสดงตัวแปรเซสชันอย่างเหมาะสม
ทำความสะอาดบ้าง
ก่อนจะไปต่อ เรามาล้างโค้ดของเรากันสักหน่อย
Meteor ช่วยให้คุณจัดระเบียบ codebase ได้อย่างมีประสิทธิภาพมากขึ้น อย่างที่คุณเห็น มีกฎที่ยากและรวดเร็วเพียงไม่กี่ข้อเท่านั้น: ทุกที่ที่คุณใส่ HTML และ JavaScript ของคุณ Meteor จะพบกฎนั้น ความยืดหยุ่นนี้เป็นสิ่งที่ดี แต่หมายความว่าคุณต้องจัดระเบียบโค้ดของคุณในแบบที่เหมาะสมมากขึ้น ดังนั้นคุณจึงไม่ต้องคอยจัดการกับความยุ่งเหยิงที่ยุ่งเหยิงขนาดมหึมา
ขั้นแรก ให้เราเปลี่ยนชื่อเทมเพลต "hello" นี้เป็นสิ่งที่มีความหมาย เช่น "bookList" และแทนที่เทมเพลต HTML ด้วยสิ่งนี้:
<head> <title>book-list</title> </head> <body> {{> bookList}} </body> <template name="bookList"> <h3>Here are some books:</h3> <UL> {{#each books}} <LI><i>{{title}}</i> by {{author}}</LI> {{/each}} </UL> </template>
ประการที่สอง ให้เราแยกส่วน "ไคลเอนต์" และ "เซิร์ฟเวอร์" ออกเป็นไฟล์แยกกัน ในไดเร็กทอรีแอปพลิเคชันของเรา เราจะตั้งค่าไดเร็กทอรีย่อย "client" และไดเร็กทอรีย่อย "server" - Meteor จะทราบโดยอัตโนมัติเพื่อเรียกใช้ไฟล์ "/client/" บนไคลเอนต์ และเรียกใช้ไฟล์ "/server/" บน เซิร์ฟเวอร์ การวางโค้ดเทมเพลตในไฟล์ JavaScript ที่ตั้งชื่อตามเทมเพลตนั้นถือเป็นเรื่องปกติ ดังนั้น ให้ใส่โค้ดไคลเอ็นต์ของเราลงใน "client/bookList.js" เราสามารถใส่รหัสเริ่มต้นเซิร์ฟเวอร์ว่างของเราใน “เซิร์ฟเวอร์/startup.js” สุดท้ายนี้ขอย้ายออก “ โค้ดเทมเพลต "client/bookList.html"
โปรดทราบว่าแม้หลังจากเปลี่ยนสิ่งนี้ Meteor จะยังคงค้นหาไฟล์ HTML และ JavaScript ทั้งหมดของเราโดยอัตโนมัติ ตราบใดที่ไฟล์นั้น อยู่ ใน “/client/” Meteor ก็จะรู้ว่าต้องเปิดไฟล์นั้นบนไคลเอนต์ ตราบใดที่ไฟล์ อยู่ ใน "/server/" meteor ก็จะรู้ว่าต้องเปิดไฟล์นั้นบนเซิร์ฟเวอร์ อีกครั้งขึ้นอยู่กับนักพัฒนาที่จะจัดระเบียบสิ่งต่างๆ
ดังนั้นตอนนี้โค้ดของเราควรมีลักษณะดังนี้:
book-list.html:
<head> <title>book-list</title> </head> <body> {{> bookList}} </body>
ลูกค้า/bookList.html:
<template name="bookList"> <h3>Here are some books:</h3> <UL> {{#each books}} <LI><i>{{title}}</i> by {{author}}</LI> {{/each}} </UL> </template>
ลูกค้า/bookList.js:
Template.bookList.rendered = function() { Session.setDefault('books', [ {title: "To Kill a Mockingbird", author: "Harper Lee"}, {title: "1984", author: "George Orwell"}, {title: "The Lord of the Rings", author: "JRR Tolkien"}, {title: "The Catcher in the Rye", author: "JD Salinger"}, {title: "The Great Gatsby", author: "F. Scott Fitzgerald"} ]); }; Template.bookList.helpers({ books: function () { return Session.get('books'); } });
เซิร์ฟเวอร์/startup.js:
Meteor.startup(function () { // code to run on server at startup }); ~~~ Check it out on MeteorPad: [Initial Code Cleanup](http://meteorpad.com/pad/MwvMcsBAzfbWwEXp3/Book-List:%20Initial%20Code%20Cleanup) Verify that everything's running correctly by checking the browser window and then we're good to move on to the next step. ## Using the Database in Meteor The Meteor server runs on top of a MongoDB database. In this section of our tutorial, we will move the static list of books out of the session variable and into that database. First, delete the Template.bookList.rendered code, so that we're no longer putting stuff into that session variable. Next, we should add that list of books to the database as fixture data when the server initializes. As you'd expect for MongoDB, Meteor stores data in "collections". So, we'll create a new collection for our books. To keep things simple we will name it "books". It turns out that both the client and the server will want to know about this collection, so we'll put this code in a new subfolder: "/lib/". Meteor knows automatically that files in "/lib/" run on the client and the server. We'll create a file called "lib/collections/books.js", and give it just one line of code: ~~~ js Books = new Meteor.Collection("books");
ภายในหน้าต่างเบราว์เซอร์ที่ชี้ไปที่ http://localhost:3000 ให้ไปที่คอนโซลนักพัฒนาซอฟต์แวร์แล้วตรวจสอบค่าของ "หนังสือ" ตอนนี้ควรเป็นคอลเลคชัน Mongo! ลองเรียกใช้ "Books.find().fetch()" แล้วคุณจะได้อาร์เรย์ที่ว่างเปล่า ซึ่งสมเหตุสมผล เนื่องจากเรายังไม่ได้เพิ่มหนังสือใดๆ เข้าไป เราสามารถลองเพิ่มรายการลงในคอนโซลได้:
Books.insert({title: "To Kill a Mockingbird", author: "Harper Lee"})
การเพิ่มสิ่งต่าง ๆ ในคอนโซลค่อนข้างน่าเบื่อ แต่เราจะตั้งค่าต่างๆ เพื่อให้เมื่อเซิร์ฟเวอร์เริ่มทำงาน เราจะแทรกข้อมูลการติดตั้งลงในฐานข้อมูลโดยอัตโนมัติ กลับไปที่ “server/startup.js” และเพิ่มสิ่งนี้:

Meteor.startup(function () { if (!Books.findOne()) { Books.insert({title: "To Kill a Mockingbird", author: "Harper Lee"}); Books.insert({title: "1984", author: "George Orwell"}); Books.insert({title: "The Lord of the Rings", author: "JRR Tolkien"}); Books.insert({title: "The Catcher in the Rye", author: "JD Salinger"}); Books.insert({title: "The Great Gatsby", author: "F. Scott Fitzgerald"}); } });
ตอนนี้ เมื่อเซิร์ฟเวอร์เริ่มทำงาน หากไม่มีข้อมูล เราจะเพิ่มข้อมูลการติดตั้ง เราสามารถตรวจสอบได้โดยกลับไปที่เทอร์มินัลของเรา หยุดเซิร์ฟเวอร์ meteor และรันคำสั่งนี้:
meteor reset
หมายเหตุ: คุณ แทบไม่ ต้องใช้คำสั่งนี้ เพราะมันรีเซ็ต เช่น เคลียร์ ฐานข้อมูลที่ Meteor ใช้อยู่ หากแอปพลิเคชัน Meteor ของคุณมีข้อมูลผู้ใช้ในฐานข้อมูล คุณไม่ควรเรียกใช้คำสั่งนี้ แต่ในกรณีนี้ เราจะล้างข้อมูลการทดสอบทั้งหมดที่เรามี
ตอนนี้เราจะเริ่มเซิร์ฟเวอร์อีกครั้ง:
meteor
เมื่อเริ่มต้น Meteor จะเรียกใช้รูทีนการเริ่มต้นใช้งาน ดูว่าฐานข้อมูลว่างเปล่า และเพิ่มข้อมูลการติดตั้ง ณ จุดนี้ ถ้าเราไปที่คอนโซลและพิมพ์ “Books.find().fetch()” เราจะได้หนังสือห้าเล่มที่เรามีมาก่อน
ที่เหลือสำหรับขั้นตอนนี้คือการแสดงหนังสือบนหน้าจอ โชคดีที่มันง่ายเหมือนกับการแทนที่ “return Session.get('books');” ด้วยตัวช่วย "หนังสือ" ต่อไปนี้:
return Books.find();
และเรากลับมาทำธุรกิจแล้ว! แอปพลิเคชันกำลังแสดงข้อมูลจากเคอร์เซอร์ฐานข้อมูล แทนที่จะแสดงจากตัวแปรเซสชัน
ลองใช้ MeteorPad: ย้ายไปที่ฐานข้อมูล
ความกังวลด้านความปลอดภัย
ฉันจะนำสิ่งนี้โดยพูดว่า: "อย่าทำเช่นนี้"
คุณคิดว่าจะเกิดอะไรขึ้นถ้ามีคนเปิดแอปนี้ในเบราว์เซอร์ ไปที่คอนโซล แล้วพิมพ์ "Books.remove({})"
คำตอบคือ: พวกเขาจะล้างคอลเล็กชันออก
นั่นเป็นปัญหาด้านความปลอดภัยที่ค่อนข้างใหญ่ ผู้ใช้ของเราเข้าถึงฐานข้อมูลของเรา มากเกินไป ลูกค้าทุกคนสามารถเข้าถึงฐานข้อมูลทั้งหมดได้ ไม่เพียงเท่านั้น ไคลเอ็นต์ใดๆ สามารถทำการ เปลี่ยนแปลงใดๆ กับฐานข้อมูลทั้งหมด ซึ่งรวมถึงการลบข้อมูล “.remove({})”
มันไม่ดีเลยมาแก้ไขกัน
Meteor ใช้สิ่งที่เรียกว่า “แพ็คเกจ” เพื่อเพิ่มฟังก์ชันการทำงาน โมดูลใดบ้างสำหรับ Node.js และอัญมณีสำหรับ Ruby แพ็คเกจเป็นชุดรวมฟังก์ชันการทำงานที่ดีสำหรับ Meteor มีแพ็คเกจสำหรับทุกสิ่ง หากต้องการเรียกดูสิ่งที่มีอยู่ ให้ดูที่ atmosphere.js
แอป meteor เริ่มต้นที่เราสร้างด้วย "meteor create" ประกอบด้วยสองแพ็คเกจที่เรียกว่า "autopublish" และ "insecure" แพ็คเกจแรกทำให้ลูกค้าสามารถเข้าถึงฐานข้อมูลทั้งหมดได้โดยอัตโนมัติ และแพ็คเกจที่สองทำให้ผู้ใช้สามารถดำเนินการใดๆ บนฐานข้อมูลนั้นได้
มาลบพวกนั้นกัน เราสามารถทำได้โดยเรียกใช้สิ่งต่อไปนี้จากไดเรกทอรีแอป:
meteor remove autopublish insecure
เมื่อเสร็จแล้ว คุณจะเห็นข้อมูลรายการหนังสือหายไปจากหน้าจอ (เนื่องจากคุณไม่สามารถเข้าถึงได้อีกต่อไป) และหากคุณลองโทร "Books.insert" คุณจะได้รับข้อผิดพลาด: "การแทรกล้มเหลว : ปฏิเสธการเข้าใช้". บน MeteorPad: Security Overkill
หากคุณไม่นำอะไรไปจากบทช่วยสอน Meteor นี้ โปรดจำไว้ว่า: เมื่อคุณปรับใช้แอพ Meteor อย่าลืมลบแพ็คเกจอัตโนมัติและไม่ปลอดภัย Meteor มีมาตรการป้องกันความปลอดภัยที่ดีหลายประการ แต่สิ่งเหล่านี้ทั้งหมดจะไม่มีประโยชน์หากคุณปล่อยสองแพ็คเกจนี้ติดตั้งไว้
เหตุใด Meteor จึงรวมแพ็คเกจเหล่านี้ไว้โดยอัตโนมัติ หากเป็นอันตรายด้านความปลอดภัย? เหตุผลก็คือ โดยเฉพาะอย่างยิ่งสำหรับผู้เริ่มต้น แพ็คเกจทั้งสองนี้ช่วยให้เริ่มต้นได้ง่ายขึ้น - คุณสามารถดีบักและปรับแต่งฐานข้อมูลได้อย่างง่ายดายจากคอนโซลของเบราว์เซอร์ แต่ควรเลิกเผยแพร่อัตโนมัติและไม่ปลอดภัยโดยเร็วที่สุด
เผยแพร่และสมัครสมาชิก
ดังนั้นเราจึงแก้ไขช่องโหว่ด้านความปลอดภัยที่อ้าปากค้าง แต่เราได้นำเสนอปัญหาสองประการ ประการแรก เราไม่สามารถเข้าถึงฐานข้อมูลได้ ประการที่สอง เราไม่มีทางโต้ตอบกับฐานข้อมูล
มาจัดการปัญหาแรกกันที่นี่ Meteor ให้การเข้าถึงฐานข้อมูลอย่างปลอดภัยโดยให้เซิร์ฟเวอร์ "เผยแพร่" ซึ่งเป็นชุดย่อยของฐานข้อมูล และให้ไคลเอ็นต์ "สมัคร" กับสิ่งพิมพ์นั้น
ขั้นแรก ให้สร้าง “/server/publications.js”:
Meteor.publish('books', function() { return Books.find({}); });
และเราจะสร้าง “/client/subscriptions.js”:
Meteor.subscribe('books');
ลองใช้ MeteorPad: เผยแพร่และสมัครสมาชิก
เซิร์ฟเวอร์ "เผยแพร่" เคอร์เซอร์ที่สามารถเข้าถึงข้อมูลทั้งหมด และลูกค้า "สมัครรับข้อมูล" ในอีกด้านหนึ่ง ไคลเอ็นต์ใช้การสมัครนี้เพื่อเติมสำเนาฐานข้อมูลที่มีข้อมูลเคอร์เซอร์ทั้งหมด เมื่อเราเข้าถึง "Books.find().fetch()" เราจะเห็นวัตถุทั้งห้าชิ้น และเราเห็นวัตถุเหล่านั้นปรากฏบนหน้าจอเหมือนเมื่อก่อน
ความแตกต่างในตอนนี้คือมันง่ายมากที่จะจำกัดสิ่งที่ลูกค้าสามารถเข้าถึงได้ ลองเปลี่ยนสิ่งพิมพ์ "find()" เป็นชุดย่อยของข้อมูล:
Meteor.publish('books', function() { return Books.find({}, {limit:3}); });
ตอนนี้ลูกค้าเห็นหนังสือเพียงสามในห้าเล่มเท่านั้น และไม่มีทางที่จะอ่านส่วนที่เหลือ ไม่เพียงแต่จะเป็นประโยชน์อย่างยิ่งต่อการรักษาความปลอดภัย (ฉันไม่เห็นบัญชีธนาคารของคนอื่น) แต่คุณสามารถใช้เพื่อส่งข้อมูลออกและหลีกเลี่ยงการบรรทุกลูกค้ามากเกินไป
การเพิ่มหนังสือใหม่
เราได้เห็นวิธีการให้ลูกค้าสามารถอ่าน-เข้าถึงฐานข้อมูลได้อย่างจำกัดและปลอดภัย ทีนี้ มาดูปัญหาที่สองกัน: เราจะให้ผู้ใช้แก้ไขฐานข้อมูลโดยไม่ให้พวกเขาทำอะไรตามต้องการได้อย่างไร การกำจัดแพ็คเกจที่ไม่ปลอดภัยทำให้ลูกค้าไม่สามารถเข้าถึงได้เลย - ลองอนุญาตให้เพิ่มหนังสืออีกครั้ง ใน meteor เราทำได้โดยเพิ่ม "method" ลงในเซิร์ฟเวอร์ มาเพิ่มวิธีการที่เพิ่มหนังสือเล่มใหม่ให้กับ “/lib/collections/books.js”:
Meteor.methods({ addBook: function(bookData) { var bookID = Books.insert(bookData); return bookID; } });
อย่างที่คุณเห็น สิ่งนี้ใช้ "bookData" - ในกรณีนี้ นั่นคือวัตถุที่มีฟิลด์ "ชื่อ" และ "ผู้แต่ง" - และเพิ่มลงในฐานข้อมูล เมื่อไคลเอนต์ของคุณโหลดซ้ำ เราสามารถเรียกวิธีนี้จากไคลเอนต์ได้ คุณสามารถไปที่คอนโซลและป้อนสิ่งนี้:
Meteor.call('addBook', {title: "A Tale of Two Cities", author: "Charles Dickens"})
และเปรี้ยง! คุณได้รับหนังสือเล่มอื่นในรายการหนังสือ การใช้คอนโซลนั้นค่อนข้างจะเทอะทะมาก เรามาเพิ่มแบบฟอร์มง่ายๆ ที่ส่วนท้ายของเทมเพลต "รายการหนังสือ" ที่จะให้เราเพิ่มหนังสือใหม่ได้:
<form class="add-book"> Title:<br> <input type="text" name="title"> <br> Author:<br> <input type="text" name="author"> <input type="submit" value="Add Book"> </form>
และเราสามารถเชื่อมต่อกับ JavaScript โดยใช้กรณีของเหตุการณ์ เช่นเดียวกับที่เรามีในแอปพลิเคชันทดสอบดั้งเดิม:
Template.bookList.events({ "submit .add-book": function(event) { event.preventDefault(); // this prevents built-in form submission Meteor.call('addBook', {title: event.target.title.value, author: event.target.author.value}) } });
คุณสามารถเห็นสิ่งนี้ในการดำเนินการบน MeteorPad: Methods
เมื่อเราไม่ปลอดภัยและเผยแพร่อัตโนมัติ ลูกค้าสามารถเข้าถึงและแก้ไขฐานข้อมูลทั้งหมดได้ ตอนนี้เมื่อความไม่ปลอดภัยและการเผยแพร่อัตโนมัติหายไป แต่ด้วยสิ่งพิมพ์ การสมัครรับข้อมูล และวิธีการ ลูกค้าสามารถเข้าถึงฐานข้อมูลและโต้ตอบกับฐานข้อมูลในลักษณะที่ควบคุมได้
ข้อสังเกต: คุณสามารถแก้ไขปัญหาด้านความปลอดภัยใน Meteor ได้โดยใช้ "กฎการอนุญาตและปฏิเสธ" คุณสามารถหาข้อมูลเพิ่มเติมเกี่ยวกับสิ่งเหล่านั้นและเหตุผลบางอย่างที่ฉันชอบแนวทางข้างต้นแทนที่ Discovermeteor.com
การตรวจสอบผู้ใช้
อาจดูเหมือนเราเพิ่งวนกลับมาที่จุดที่เราเริ่มต้น แต่มีข้อแตกต่างที่สำคัญประการหนึ่ง คือ ตอนนี้เราจำกัดการเข้าถึงฐานข้อมูลได้ง่ายมาก หากต้องการดูวิธีการทำงาน ให้ลองเพิ่มผู้ใช้ในแอปนี้ เราจะเพิ่มระบบเข้าสู่ระบบในแอปของเรา จากนั้นแทนที่จะให้ลูกค้าทั้งหมดทำงานกับรายการหนังสือทั้งระบบ เราจะสร้างระบบดังกล่าวเพื่อให้ผู้ใช้แต่ละรายสามารถเพิ่มหรืออ่านรายชื่อหนังสือของตนเองได้เท่านั้น
ไปที่ไดเร็กทอรีแอพและติดตั้งสองแพ็คเกจ:
meteor add accounts-ui accounts-password
ที่นั่น. คุณเพิ่งเพิ่มระบบเข้าสู่ระบบในแอป ตอนนี้เราเพียงแค่ต้องเพิ่ม UI การเข้าสู่ระบบใน book-list.html วางบรรทัดเดียวนี้ไว้ที่ส่วนบนของร่างกาย:
{{> loginButtons}}
คุณควรเห็นข้อความแจ้งการเข้าสู่ระบบที่ด้านบนของหน้าจอ:
โปรดทราบว่าหากคุณคลิกลิงก์เข้าสู่ระบบ ระบบจะขอที่อยู่อีเมลและรหัสผ่าน เราสามารถสลับไปใช้ระบบเข้าสู่ระบบชื่อผู้ใช้/รหัสผ่านแบบง่ายได้โดยสร้าง “/client/config.js” โดยมีข้อมูลต่อไปนี้
Accounts.ui.config({ passwordSignupFields: "USERNAME_ONLY" });
ณ จุดนี้ คุณสามารถพิมพ์ “Meteor.userId()” ในคอนโซล และมันจะส่งคืน “null” คุณสามารถลองคลิกลิงก์เพื่อสร้างบัญชี การเรียก “Meteor.userId()” ควรส่งคืนสตริง ID เซิร์ฟเวอร์มีสิทธิ์เข้าถึงข้อมูลชิ้นเดียวกันนี้ (เช่น “this.userId”) ดังนั้นจึงเป็นเรื่องเล็กน้อยที่จะทำให้วิธีการ “เพิ่มหนังสือ” บังคับให้ผู้ใช้เข้าสู่ระบบและรวมฟิลด์ ID ผู้ใช้:
Meteor.methods({ addBook: function(bookData) { if (this.userId) { bookData.userID = this.userId; var bookID = Books.insert(bookData); return bookID; } } });
สิ่งที่เหลืออยู่ในตอนนี้คือการจำกัดไคลเอนต์ โดยแสดงเฉพาะหนังสือที่ผู้ใช้รายนี้เพิ่มเข้าไป เราใช้ความสามารถของสิ่งพิมพ์ในการจำกัดสิ่งที่ลูกค้าสามารถเข้าถึงได้:
Meteor.publish('books', function() { return Books.find({userID: this.userId}); });
ขณะนี้ สิ่งพิมพ์พบเฉพาะหนังสือจากผู้ใช้รายนี้เท่านั้น เรายังสามารถเข้าถึง userId จากนิพจน์ Blaze เป็น “{{currentUser}}”; และเราสามารถใช้สิ่งนี้ได้ด้วยคำสั่ง “{{#if}}” (ซึ่งทำสิ่งที่คุณคิดจริงๆ) เพื่อแสดงข้อมูลเมื่อผู้ใช้เข้าสู่ระบบเท่านั้น:
<template name="bookList"> {{#if currentUser}} <h3>Here are your books:</h3> <UL> {{#each books}} <LI><i>{{title}}</i> by {{author}}</LI> {{/each}} </UL> <form class="add-book"> Title:<br> <input type="text" name="title"> <br> Author:<br> <input type="text" name="author"> <input type="submit" value="Add Book"> </form> {{else}} <h3>Please log in to see your books</h3> {{/if}} </template>
ดูผลลัพธ์สุดท้ายบน MeteorPad: Users
การปรับใช้
ตอนนี้เราสามารถปรับใช้แอปพลิเคชั่น Meteor นี้กับอินเทอร์เน็ตได้ เราทำสิ่งนี้โดยไปที่ไดเร็กทอรีแอปพลิเคชันบนเทอร์มินัลแล้วดำเนินการ:
meteor deploy <your app's name>.meteor.com
ตรวจสอบให้แน่ใจว่าคุณได้แทนที่ “<ชื่อแอปของคุณ>” ด้วยชื่อย่อจริงสำหรับอินสแตนซ์ของแอปพลิเคชัน การเรียกใช้คำสั่งนี้จะแจ้งให้คุณตั้งค่าบัญชีกับ Meteor จากนั้นแอปพลิเคชันใหม่ของคุณจะอยู่บนเซิร์ฟเวอร์ทดสอบของ Meteor เพื่อให้คุณสามารถทดลองใช้งานบนอินเทอร์เน็ตได้
สำหรับการสาธิตอย่างรวดเร็ว โซลูชัน meteor.com นี้คือทั้งหมดที่คุณต้องการ ทีม Meteor ไม่ได้ประกาศข้อจำกัดที่ชัดเจนในการจัดเก็บข้อมูลหรือแบนด์วิดท์บนเซิร์ฟเวอร์ของตน ข้อจำกัดที่น่าสังเกตเพียงอย่างเดียวคือหากแอปของคุณไม่ได้ใช้งานเป็นเวลานาน เว็บไซต์จะใช้เวลาสองสามวินาทีในการเปิดใช้งานสำหรับผู้ใช้รายต่อไป
ที่กล่าวว่า meteor.com ไม่ได้มีไว้สำหรับใช้ในเชิงพาณิชย์ แต่เมื่อคุณเข้าสู่ขั้นตอนการผลิต มีบริษัทที่ให้บริการแพลตฟอร์มเช่น Modulus และ Digital Ocean ที่ทำให้การปรับใช้แอพ Meteor เป็นเรื่องง่าย หากคุณต้องการปรับใช้แอพ meteor บนเซิร์ฟเวอร์ของคุณเอง "meteor up" จะทำให้กระบวนการนั้นตรงไปตรงมาเช่นกัน
ขั้นตอนถัดไป
ยินดีด้วย! ในการแสวงหาการเรียนรู้ Meteor คุณได้สร้างและใช้งานเว็บแอปพลิเคชัน Meteor แบบเรียลไทม์ที่ง่ายมาก เห็นได้ชัดว่านี่เป็นเพียงก้าวแรกเล็กๆ สู่จักรวาลแห่งคุณลักษณะและฟังก์ชันการทำงาน หากคุณชอบสิ่งที่คุณเคยเห็นมา ฉันขอแนะนำ Your First Meteor Application โดย David Turnbull ซึ่งจะแนะนำผู้อ่านเกี่ยวกับการสร้างแอปพลิเคชันที่ซับซ้อนยิ่งขึ้น พร้อมด้วยข้อมูลเพิ่มเติมเกี่ยวกับคุณสมบัติของดาวตกตลอดเส้นทาง มีให้ในรูปแบบหนังสือ Kindle ในราคาเล็กน้อยและเป็น PDF ฟรีบนเว็บไซต์ของ Turnbull
คุณจะต้องสำรวจแพ็คเกจที่มีให้สำหรับ Meteor ด้วย เก้าครั้งในสิบ คำตอบของ "ฉันจะ <x> ใน Meteor ได้อย่างไร" คือ “มีแพ็คเกจสำหรับสิ่งนั้น” “ฉันจะเพิ่มการกำหนดเส้นทางไปยังแอปพลิเคชันของฉันได้อย่างไร” คุณใช้เราเตอร์เหล็ก “ฉันจะจัดหา RESTful API ได้อย่างไร” คุณใช้ RESTivus “ฉันจะรวมการทดสอบหน่วยได้อย่างไร” คุณใช้ความเร็ว “ฉันจะเพิ่มการตรวจสอบสคีมาได้อย่างไร” คุณใช้ Collection2 คุณสามารถหลงทางใน Atmosphere.js ได้อย่างง่ายดายเมื่อดูแพ็คเกจที่มีทั้งหมด
ทำไมไม่ใช้ Meteor?
ดังที่คุณเห็นจากบทช่วยสอนนี้ Meteor นั้นเรียบง่ายและสนุกในการเขียนแอปพลิเคชัน แต่ฉันจะพลาดเองหากไม่ได้กล่าวถึงข้อเสีย
ดาวตกยังค่อนข้างอ่อน มันมาถึง 1.0 เมื่อเดือนตุลาคมที่ผ่านมา และนั่นนำไปสู่ปัญหาบางอย่าง หากคุณต้องการทำอะไรที่คลุมเครือ อาจยังไม่มีใครเขียนแพ็คเกจสำหรับฟังก์ชันนั้นมาก่อน แพ็คเกจที่มีอยู่นั้นมีแนวโน้มที่จะมีจุดบกพร่องมากกว่า เพียงเพราะพวกเขาไม่ได้อยู่มานานพอที่จะแก้ปัญหาทั้งหมดได้
นอกจากนี้ Meteor ยังไม่ค่อยรู้จักการสเกล มีไซต์ Meteor มากมายที่ขยายได้ถึงจำนวนผู้ใช้ที่สมเหตุสมผล แต่มีไซต์ขนาดใหญ่เพียงไม่กี่ไซต์ - ไม่มีอะไรในลำดับของ Facebook หรือ LinkedIn ที่มีผู้ใช้หลายสิบหรือหลายร้อยล้านคน
อย่างไรก็ตาม สำหรับแอปพลิเคชั่นส่วนใหญ่ Meteor เป็นตัวเลือกที่สมบูรณ์แบบ เนื่องจากเป็นโอกาสที่จะลดเวลาในการพัฒนาและมีส่วนร่วมในการเริ่มต้นสิ่งที่ยอดเยี่ยม