portaldacalheta.pt
  • หลัก
  • การทำกำไรและประสิทธิภาพ
  • การออกแบบ Ux
  • เทคโนโลยี
  • การออกแบบตราสินค้า
เทคโนโลยี

Webpack หรือ Browserify & Gulp: ไหนดีกว่ากัน?



เนื่องจากเว็บแอปพลิเคชันมีความซับซ้อนมากขึ้นการทำให้เว็บแอปของคุณสามารถปรับขนาดได้จึงมีความสำคัญสูงสุด ในขณะที่การเขียน ad-hoc JavaScript และ jQuery ในอดีตจะเพียงพอ แต่ในปัจจุบันการสร้างเว็บแอปนั้นจำเป็นต้องมีระเบียบวินัยและแนวทางปฏิบัติในการพัฒนาซอฟต์แวร์อย่างเป็นทางการมากขึ้นเช่น:

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

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



การแลกเปลี่ยนเครื่องมือ Bundling: Webpack กับ Browserify



คุณควรใช้เครื่องมือบันเดิลใด: Webpack หรือ Browserify + Gulp นี่คือคำแนะนำในการเลือก ทวีต

นอกจากนี้ยังเป็นเรื่องปกติที่จะใช้ตัวประมวลผลล่วงหน้าของภาษาเช่น SASS และ JSX ที่คอมไพล์กับ JS และ CSS ดั้งเดิมตลอดจนตัวส่งสัญญาณ JS เช่น Babel เพื่อให้ได้รับประโยชน์จากโค้ด ES6 ในขณะที่ยังคงความเข้ากันได้กับ ES5



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

ฉันจะใช้ อึก ในฐานะนักวิ่งงานเพราะเป็นมิตรกับนักพัฒนาเรียนรู้ง่ายและเข้าใจได้ง่าย



ข้อมูลเบื้องต้นเกี่ยวกับอึก

API ของ Gulp ประกอบด้วยสี่ฟังก์ชัน:

การปรับแต่งประสิทธิภาพเซิร์ฟเวอร์ sql 2014
  • gulp.src
  • gulp.dest
  • gulp.task
  • gulp.watch

Gulp ทำงานอย่างไร



ตัวอย่างเช่นในที่นี้เป็นงานตัวอย่างที่ใช้ฟังก์ชันสามในสี่ฟังก์ชันนี้:

gulp.task('my-first-task', function() { gulp.src('/public/js/**/*.js') .pipe(concat()) .pipe(minify()) .pipe(gulp.dest('build')) });

เมื่อ my-first-task จะดำเนินการไฟล์ทั้งหมดที่ตรงกับรูปแบบ glob /public/js/**/*.js ถูกลดขนาดแล้วโอนไปที่ build โฟลเดอร์



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

ขั้นตอนต่อไปในการทำความเข้าใจ Gulp คือการทำความเข้าใจอาร์เรย์ของการอ้างอิงงาน



gulp.task('my-second-task', ['lint', 'bundle'], function() { ... });

ที่นี่ my-second-task เรียกใช้ฟังก์ชันการโทรกลับหลังจาก lint เท่านั้น และ bundle งานจะเสร็จสมบูรณ์ สิ่งนี้ช่วยให้แยกข้อกังวล: คุณสร้างชุดงานเล็ก ๆ ด้วยความรับผิดชอบเดียวเช่นการแปลง LESS เป็น CSS และสร้างงานหลักที่เรียกใช้งานอื่น ๆ ทั้งหมดผ่านอาร์เรย์ของการอ้างอิงงาน

ในที่สุดเราก็มี gulp.watch ซึ่งคอยดูรูปแบบไฟล์ glob สำหรับการเปลี่ยนแปลงและเมื่อตรวจพบการเปลี่ยนแปลงจะเรียกใช้ชุดของงาน



gulp.task('my-third-task', function() { gulp.watch('/public/js/**/*.js', ['lint', 'reload']) })

ในตัวอย่างข้างต้นการเปลี่ยนแปลงใด ๆ ในการจับคู่ไฟล์ /public/js/**/*.js จะเรียก lint และ reload งาน. การใช้งานทั่วไปของ gulp.watch คือการเรียกใช้การโหลดซ้ำในเบราว์เซอร์ซึ่งเป็นคุณลักษณะที่มีประโยชน์มากสำหรับการพัฒนาที่คุณจะขาดไม่ได้เมื่อได้สัมผัส

และเช่นเดียวกับที่คุณเข้าใจทั้งหมดที่คุณจำเป็นต้องรู้ gulp

Webpack พอดีที่ไหน?

Webpack ทำงานอย่างไร

เมื่อใช้รูปแบบ CommonJS การรวมไฟล์ JavaScript ไม่ง่ายเหมือนการต่อไฟล์เข้าด้วยกัน แต่คุณมีจุดเริ่มต้น (โดยปกติเรียกว่า index.js หรือ app.js) พร้อมด้วยชุดของ require หรือ import คำสั่งที่ด้านบนของไฟล์:

ES5

var Component1 = require('./components/Component1'); var Component2 = require('./components/Component2');

ES6

import Component1 from './components/Component1'; import Component2 from './components/Component2';

การอ้างอิงต้องได้รับการแก้ไขก่อนโค้ดที่เหลือใน app.js และการอ้างอิงเหล่านั้นอาจมีการอ้างอิงเพิ่มเติมเพื่อแก้ไข นอกจากนี้คุณอาจ require การอ้างอิงเดียวกันในหลาย ๆ ที่ในแอปพลิเคชันของคุณ แต่คุณต้องการแก้ไขการอ้างอิงนั้นเพียงครั้งเดียว อย่างที่คุณสามารถจินตนาการได้ว่าเมื่อคุณมีแผนผังการพึ่งพาสองสามระดับขั้นตอนการรวม JavaScript ของคุณจะค่อนข้างซับซ้อน นี่คือที่บันเดิลเลอร์เช่น Browserify และ Webpack เข้ามา

เหตุใดนักพัฒนาจึงใช้ Webpack แทนที่จะใช้ Gulp

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

พูดง่ายๆคือ Webpack เป็นเครื่องมือที่ทรงพลังที่สามารถทำงานส่วนใหญ่ที่คุณทำผ่านนักวิ่งงานได้ ตัวอย่างเช่น Webpack มีตัวเลือกสำหรับการย่อขนาดและซอร์สแมปสำหรับบันเดิลของคุณอยู่แล้ว นอกจากนี้ Webpack ยังสามารถทำงานเป็นมิดเดิลแวร์ผ่านเซิร์ฟเวอร์ที่กำหนดเองชื่อ webpack-dev-server ซึ่งรองรับทั้งการโหลดซ้ำแบบสดและการโหลดซ้ำแบบร้อน (เราจะพูดถึงคุณลักษณะเหล่านี้ในภายหลัง) เมื่อใช้รถตักคุณยังสามารถเพิ่ม ES6 ไปยัง ES5 Transpilation และ CSS pre-and post-processors นั่นเป็นเพียงแค่ปล่อยให้การทดสอบหน่วยและการขุยเป็นงานหลักที่ Webpack ไม่สามารถจัดการได้อย่างอิสระ เนื่องจากเราได้ลดงานอึกอย่างน้อยครึ่งโหลลงเหลือสองงานนักพัฒนาจำนวนมากเลือกที่จะใช้สคริปต์ NPM โดยตรงแทนเนื่องจากจะหลีกเลี่ยงค่าใช้จ่ายในการเพิ่ม Gulp ในโครงการ (ซึ่งเราจะพูดถึงในภายหลัง) .

ข้อเสียเปรียบที่สำคัญในการใช้ Webpack คือการกำหนดค่าค่อนข้างยากซึ่งไม่น่าสนใจหากคุณพยายามทำให้โปรเจ็กต์ทำงานได้อย่างรวดเร็ว

การตั้งค่า Task Runner 3 รายการของเรา

ฉันจะตั้งค่าโปรเจ็กต์ด้วยการตั้งค่าตัววิ่งงานที่แตกต่างกันสามแบบ การตั้งค่าแต่ละครั้งจะทำงานต่อไปนี้:

  • ตั้งค่าเซิร์ฟเวอร์การพัฒนาด้วยการโหลดซ้ำแบบสดเมื่อมีการเปลี่ยนแปลงไฟล์ที่เฝ้าดู
  • รวมไฟล์ JS & CSS ของเรา (รวมถึงการถ่ายโอน ES6 ถึง ES5, การแปลง SASS เป็น CSS และแผนผังแหล่งที่มา) ในลักษณะที่ปรับขนาดได้ในการเปลี่ยนแปลงไฟล์ที่เฝ้าดู
  • เรียกใช้การทดสอบหน่วยไม่ว่าจะเป็นงานแบบสแตนด์อโลนหรือในโหมดนาฬิกา
  • เรียกใช้ผ้าสำลีเป็นงานแบบสแตนด์อโลนหรือในโหมดนาฬิกา
  • ให้ความสามารถในการดำเนินการทั้งหมดข้างต้นผ่านคำสั่งเดียวในเทอร์มินัล
  • มีคำสั่งอื่นสำหรับการสร้างบันเดิลการผลิตที่มีการลดขนาดและการเพิ่มประสิทธิภาพอื่น ๆ

การตั้งค่าทั้งสามของเราคือ:

  • อึก + Browserify
  • อึก + Webpack
  • สคริปต์ Webpack + NPM

แอปพลิเคชันจะใช้ ตอบสนอง สำหรับส่วนหน้า เดิมทีฉันต้องการใช้วิธีการที่ไม่เชื่อเรื่องพระเจ้าของกรอบงาน แต่การใช้ React ช่วยลดความซับซ้อนของความรับผิดชอบของนักวิ่งงานเนื่องจากต้องการไฟล์ HTML เพียงไฟล์เดียวและ React ทำงานได้ดีกับรูปแบบ CommonJS

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

ฉันได้ตั้งค่าที่เก็บ Git โดยมีสามสาขาหนึ่งแห่งสำหรับแต่ละแนวทาง ( ลิงค์ ). การทดสอบการตั้งค่าแต่ละครั้งทำได้ง่ายๆดังนี้:

git checkout npm prune (optional) npm install gulp (or npm start, depending on the setup)

มาตรวจสอบรหัสในแต่ละสาขาโดยละเอียด ...

รหัสทั่วไป

โครงสร้างโฟลเดอร์

- app - components - fonts - styles - index.html - index.js - index.test.js - routes.js

index.html

ไฟล์ HTML ที่ตรงไปตรงมา แอปพลิเคชัน React ถูกโหลดเข้ามาและเราใช้ไฟล์ JS และ CSS ที่มาพร้อมกับไฟล์เดียวเท่านั้น ในความเป็นจริงในการตั้งค่าการพัฒนา Webpack เราไม่จำเป็นต้องมี bundle.css ด้วยซ้ำ

index.js

ซึ่งทำหน้าที่เป็นจุดเข้า JS ของแอปของเรา โดยพื้นฐานแล้วเราแค่โหลด React Router ลงใน div ด้วย id app ที่เรากล่าวถึงก่อนหน้านี้

เส้นทาง js

ฟรีหมายเลขบัตรเครดิตที่ถูกแฮ็กด้วย cvv

ไฟล์นี้กำหนดเส้นทางของเรา URL /, /about และ /contact ถูกแมปกับ HomePage, AboutPage และ ContactPage ส่วนประกอบตามลำดับ

index.test.js

นี่คือชุดของการทดสอบหน่วยที่ทดสอบพฤติกรรม JavaScript ดั้งเดิม ในแอปคุณภาพการผลิตจริงคุณจะต้องเขียนการทดสอบหน่วยต่อองค์ประกอบการตอบสนอง (อย่างน้อยก็การทดสอบที่ปรับเปลี่ยนสถานะ) ทดสอบพฤติกรรมเฉพาะของปฏิกิริยา อย่างไรก็ตามสำหรับจุดประสงค์ของโพสต์นี้เพียงแค่มีการทดสอบหน่วยการทำงานที่สามารถทำงานในโหมดนาฬิกาได้ก็เพียงพอแล้ว

ส่วนประกอบ / App.js

สิ่งนี้ถือได้ว่าเป็นคอนเทนเนอร์สำหรับการดูหน้าเว็บทั้งหมดของเรา แต่ละหน้ามีความสอดคล้องเช่นเดียวกับ this.props.children ซึ่งประเมินเป็นการดูหน้าเว็บ (เช่น / ContactPage ถ้าที่ /contact ในเบราว์เซอร์)

ส่วนประกอบ / home / HomePage.js

นี่คือมุมมองบ้านของเรา ฉันเลือกใช้ react-bootstrap เนื่องจากระบบกริดของ bootstrap นั้นยอดเยี่ยมสำหรับการสร้างเพจที่ตอบสนอง ด้วยการใช้ bootstrap อย่างเหมาะสมจำนวนคิวรีสื่อที่คุณต้องเขียนสำหรับวิวพอร์ตขนาดเล็กจะลดลงอย่างมาก

ส่วนประกอบที่เหลือ (Header, AboutPage, ContactPage) มีโครงสร้างคล้ายกัน (react-bootstrap มาร์กอัปไม่มีการจัดการสถานะ)

ตอนนี้เรามาพูดถึงการจัดแต่งทรงผมกันดีกว่า

แนวทางการจัดรูปแบบ CSS

แนวทางที่ฉันชอบในการจัดแต่งทรงผมส่วนประกอบ React คือการมีหนึ่งสไตล์ชีตต่อหนึ่งองค์ประกอบซึ่งสไตล์จะถูกกำหนดขอบเขตให้ใช้กับส่วนประกอบเฉพาะนั้นเท่านั้น คุณจะสังเกตเห็นว่าในองค์ประกอบการตอบสนองแต่ละส่วนของฉันคือระดับบนสุด div มีชื่อคลาสที่ตรงกับชื่อของส่วนประกอบ ตัวอย่างเช่น HomePage.js มีมาร์กอัปห่อโดย:

...

นอกจากนี้ยังมี HomePage.scss ไฟล์ที่มีโครงสร้างดังนี้:

@import '../../styles/variables'; .HomePage { // Content here }

เหตุใดแนวทางนี้จึงมีประโยชน์มาก ส่งผลให้ CSS แบบโมดูลาร์สูงซึ่งส่วนใหญ่ช่วยขจัดปัญหาของพฤติกรรมการเรียงซ้อนที่ไม่ต้องการ

สมมติว่าเรามีส่วนประกอบของปฏิกิริยาสองตัว Component1 และ Component2. ในทั้งสองกรณีเราต้องการแทนที่ h2 ขนาดตัวอักษร.

/* Component1.scss */ .Component1 { h2 { font-size: 30px; } } /* Component2.scss */ .Component2 { h2 { font-size: 60px; } }

h2 ขนาดตัวอักษรของ Component1 และ Component2 เป็นอิสระไม่ว่าส่วนประกอบจะอยู่ติดกันหรือส่วนประกอบหนึ่งซ้อนอยู่ภายในอีกส่วนหนึ่ง ตามหลักการแล้วนี่หมายความว่าการจัดแต่งทรงผมของส่วนประกอบนั้นมีอยู่ในตัวเองโดยสมบูรณ์หมายความว่าส่วนประกอบจะมีลักษณะเหมือนกันทุกประการไม่ว่าจะวางไว้ที่ใดในมาร์กอัปของคุณ ในความเป็นจริงมันไม่ง่ายเสมอไป แต่มันเป็นก้าวที่ยิ่งใหญ่ในทิศทางที่ถูกต้อง

เครื่องมือทดสอบหน่วยสำหรับ net

นอกจากรูปแบบต่อองค์ประกอบแล้วฉันยังต้องการ styles โฟลเดอร์ที่มีสไตล์ชีตส่วนกลาง global.scss พร้อมกับส่วน SASS ที่จัดการความรับผิดชอบเฉพาะ (ในกรณีนี้คือ _fonts.scss และ _variables.scss สำหรับฟอนต์และตัวแปรตามลำดับ) สไตล์ชีตส่วนกลางช่วยให้เราสามารถกำหนดรูปลักษณ์ทั่วไปของแอปทั้งหมดได้ในขณะที่สไตล์ชีตส่วนช่วยสามารถนำเข้าโดยใช้สไตล์ชีตต่อองค์ประกอบได้ตามต้องการ

ตอนนี้โค้ดทั่วไปในแต่ละสาขาได้รับการสำรวจในเชิงลึกแล้วเรามาเปลี่ยนโฟกัสของเราไปที่แนวทางของนักวิ่งภารกิจแรก / บันเดิลเลอร์

การตั้งค่า Gulp + Browserify

gulpfile.js

สิ่งนี้ออกมาเป็น gulpfile ขนาดใหญ่อย่างน่าประหลาดใจโดยมีการนำเข้า 22 รายการและโค้ด 150 บรรทัด ดังนั้นเพื่อความกระชับฉันจะตรวจสอบเฉพาะ js, css, server, watch และ default งานโดยละเอียด

ชุด JS

// Browserify specific configuration const b = browserify({ entries: [config.paths.entry], debug: true, plugin: PROD ? [] : [hmr, watchify], cache: {}, packageCache: {} }) .transform('babelify'); b.on('update', bundle); b.on('log', gutil.log); (...) gulp.task('js', bundle); (...) // Bundles our JS using Browserify. Sourcemaps are used in development, while minification is used in production. function bundle() { return b.bundle() .on('error', gutil.log.bind(gutil, 'Browserify Error')) .pipe(source('bundle.js')) .pipe(buffer()) .pipe(cond(PROD, minifyJS())) .pipe(cond(!PROD, sourcemaps.init({loadMaps: true}))) .pipe(cond(!PROD, sourcemaps.write())) .pipe(gulp.dest(config.paths.baseDir)); }

วิธีนี้ค่อนข้างน่าเกลียดด้วยเหตุผลหลายประการ ประการหนึ่งคืองานแบ่งออกเป็นสามส่วนแยกกัน ขั้นแรกให้คุณสร้างออบเจ็กต์กลุ่ม Browserify b ส่งผ่านตัวเลือกบางตัวและกำหนดตัวจัดการเหตุการณ์บางอย่าง จากนั้นคุณจะมีงาน Gulp เองซึ่งจะต้องส่งผ่านฟังก์ชันที่มีชื่อเป็นการเรียกกลับแทนการฝังใน (เนื่องจาก b.on('update') ใช้การโทรกลับแบบเดียวกัน) สิ่งนี้แทบจะไม่มีความสง่างามของงานอึกที่คุณเพิ่งผ่านไป gulp.src และท่อการเปลี่ยนแปลงบางอย่าง

อีกประเด็นหนึ่งคือสิ่งนี้บังคับให้เรามีวิธีการโหลดซ้ำ html, css และ js ในเบราว์เซอร์ มองไปที่อึกของเรา watch งาน:

gulp.task('watch', () => { livereload.listen({basePath: 'dist'}); gulp.watch(config.paths.html, ['html']); gulp.watch(config.paths.css, ['css']); gulp.watch(config.paths.js, () => { runSequence('lint', 'test'); }); });

เมื่อไฟล์ HTML มีการเปลี่ยนแปลง html งานถูกรันใหม่

gulp.task('html', () => { return gulp.src(config.paths.html) .pipe(gulp.dest(config.paths.baseDir)) .pipe(cond(!PROD, livereload())); });

ท่อสุดท้ายเรียก livereload() ถ้า NODE_ENV ไม่ใช่ production ซึ่งทำให้เกิดการรีเฟรชในเบราว์เซอร์

ใช้ตรรกะเดียวกันกับนาฬิกา CSS เมื่อไฟล์ CSS มีการเปลี่ยนแปลง css งานถูกรันอีกครั้งและไปป์สุดท้ายใน css ทริกเกอร์งาน livereload() และรีเฟรชเบราว์เซอร์

อย่างไรก็ตาม js นาฬิกาไม่เรียกว่า js งานเลย ตัวจัดการเหตุการณ์ของ Browserify b.on('update', bundle) จัดการการรีโหลดโดยใช้วิธีการที่แตกต่างกันโดยสิ้นเชิง (กล่าวคือการเปลี่ยนโมดูลร้อน) ความไม่สอดคล้องกันในแนวทางนี้เป็นสิ่งที่น่ารำคาญ แต่น่าเสียดายที่จำเป็นเพื่อให้มี เพิ่มขึ้น สร้าง ถ้าเราเรียกอย่างไร้เดียงสาว่า livereload() ในตอนท้ายของ bundle ฟังก์ชันนี้จะสร้างไฟล์ ทั้งหมด JS บันเดิลในการเปลี่ยนแปลงไฟล์ JS แต่ละไฟล์ เห็นได้ชัดว่าแนวทางดังกล่าวไม่ได้ขยายขนาด ยิ่งคุณมีไฟล์ JS มากเท่าไหร่การรวมกลุ่มใหม่แต่ละครั้งก็จะใช้เวลานานขึ้น ทันใดนั้นการคืนเงิน 500 มิลลิวินาทีของคุณจะเริ่มขึ้นโดยใช้เวลา 30 วินาทีซึ่งขัดขวางการพัฒนาที่คล่องตัวอย่างแท้จริง

ชุด CSS

gulp.task('css', () => { return gulp.src( [ 'node_modules/bootstrap/dist/css/bootstrap.css', 'node_modules/font-awesome/css/font-awesome.css', config.paths.css ] ) .pipe(cond(!PROD, sourcemaps.init())) .pipe(sass().on('error', sass.logError)) .pipe(concat('bundle.css')) .pipe(cond(PROD, minifyCSS())) .pipe(cond(!PROD, sourcemaps.write())) .pipe(gulp.dest(config.paths.baseDir)) .pipe(cond(!PROD, livereload())); });

ประเด็นแรกคือการรวม CSS ของผู้ขายที่ยุ่งยาก เมื่อใดก็ตามที่มีการเพิ่มไฟล์ CSS ของผู้ให้บริการรายใหม่ในโปรเจ็กต์เราต้องจำไว้ว่าให้เปลี่ยน gulpfile ของเราเพื่อเพิ่มองค์ประกอบลงใน gulp.src อาร์เรย์แทนที่จะเพิ่มการนำเข้าลงในตำแหน่งที่เกี่ยวข้องในซอร์สโค้ดจริงของเรา

ปัญหาหลักอื่น ๆ คือตรรกะที่ซับซ้อนในแต่ละท่อ ฉันต้องเพิ่มไลบรารี NPM ชื่อ gulp-cond เพียงเพื่อตั้งค่าตรรกะเงื่อนไขในไปป์ของฉันและผลลัพธ์สุดท้ายก็ไม่สามารถอ่านได้ (วงเล็บสามอันทุกที่!)

งานเซิร์ฟเวอร์

gulp.task('server', () => { nodemon({ script: 'server.js' }); });

งานนี้ตรงไปตรงมามาก โดยพื้นฐานแล้วมันเป็นกระดาษห่อหุ้มรอบการเรียกใช้บรรทัดคำสั่ง nodemon server.js ซึ่งรัน server.js ในสภาพแวดล้อมโหนด nodemon ใช้แทน node เพื่อให้การเปลี่ยนแปลงใด ๆ ในไฟล์ทำให้ไฟล์รีสตาร์ท โดยค่าเริ่มต้น nodemon จะรีสตาร์ทกระบวนการทำงานบน ใด ๆ การเปลี่ยนไฟล์ JS ด้วยเหตุนี้การรวม nodemon.json จึงเป็นเรื่องสำคัญ ไฟล์เพื่อ จำกัด ขอบเขต:

{ 'watch': 'server.js' }

มาดูรหัสเซิร์ฟเวอร์ของเรากัน

เซิร์ฟเวอร์ js

const baseDir = process.env.NODE_ENV === 'production' ? 'build' : 'dist'; const port = process.env.NODE_ENV === 'production' ? 8080: 3000; const app = express();

สิ่งนี้ตั้งค่าไดเร็กทอรีฐานของเซิร์ฟเวอร์และพอร์ตตามสภาพแวดล้อมโหนดและสร้างอินสแตนซ์ของ Express

app.use(require('connect-livereload')({port: 35729})); app.use(express.static(path.join(__dirname, baseDir)));

สิ่งนี้เพิ่ม connect-livereload มิดเดิลแวร์ (จำเป็นสำหรับการตั้งค่าการโหลดซ้ำของเรา) และมิดเดิลแวร์แบบคงที่ (จำเป็นสำหรับการจัดการสินทรัพย์คงที่ของเรา)

app.get('/api/sample-route', (req, res) => { res.send({ website: 'ApeeScape', blogPost: true }); });

นี่เป็นเพียงเส้นทาง API ธรรมดา หากคุณไปที่ localhost:3000/api/sample-route ในเบราว์เซอร์คุณจะเห็น:

{ website: 'ApeeScape', blogPost: true }

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

app.get('*', (req, res) => { res.sendFile(path.join(__dirname, './', baseDir ,'/index.html')); });

นี่คือเส้นทางที่ตรวจจับทั้งหมดซึ่งหมายความว่าไม่ว่าคุณจะพิมพ์ url ใดลงในเบราว์เซอร์เซิร์ฟเวอร์จะส่งคืนข้อความเดียวของเรา index.html หน้า. จากนั้นเป็นความรับผิดชอบของ React Router ในการแก้ไขเส้นทางของเราในฝั่งไคลเอ็นต์

app.listen(port, () => { open(`http://localhost:${port}`); });

สิ่งนี้จะบอกให้อินสแตนซ์ด่วนของเราฟังพอร์ตที่เราระบุและเปิดเบราว์เซอร์ในแท็บใหม่ที่ URL ที่ระบุ

สิ่งเดียวที่ฉันไม่ชอบเกี่ยวกับการตั้งค่าเซิร์ฟเวอร์คือ:

app.use(require('connect-livereload')({port: 35729}));

ระบุว่าเราใช้ gulp-livereload อยู่แล้ว ใน gulpfile ของเราสิ่งนี้ทำให้สองสถานที่แยกกันซึ่งต้องใช้ livereload

ตอนนี้สุดท้าย แต่ไม่ท้ายสุด:

งานเริ่มต้น

gulp.task('default', (cb) => { runSequence('clean', 'lint', 'test', 'html', 'css', 'js', 'fonts', 'server', 'watch', cb); });

นี่คืองานที่ทำงานเมื่อพิมพ์ gulp เข้าไปในเทอร์มินัล ความแปลกอย่างหนึ่งคือต้องใช้ runSequence เพื่อให้งานรันตามลำดับ โดยปกติอาร์เรย์ของงานจะดำเนินการควบคู่กันไป แต่นี่ไม่ใช่พฤติกรรมที่ต้องการเสมอไป ตัวอย่างเช่นเราต้องมี clean เรียกใช้งานก่อน html เพื่อให้แน่ใจว่าโฟลเดอร์ปลายทางของเราว่างเปล่าก่อนที่จะย้ายไฟล์เข้ามา เมื่อปล่อยอึก 4 มันจะรองรับ gulp.series และ gulp.parallel วิธีการโดยกำเนิด แต่สำหรับตอนนี้เราต้องทิ้งไว้ด้วยมุมแหลมเล็กน้อยนี้ในการตั้งค่าของเรา

ยิ่งไปกว่านั้นนี่คือความสง่างามจริงๆ การสร้างและโฮสต์แอปทั้งหมดของเราดำเนินการในคำสั่งเดียวและการทำความเข้าใจส่วนใดส่วนหนึ่งของเวิร์กโฟลว์นั้นทำได้ง่ายเพียงแค่ตรวจสอบงานแต่ละงานในลำดับการรัน นอกจากนี้เราสามารถแบ่งลำดับทั้งหมดออกเป็นกลุ่มย่อย ๆ เพื่อเป็นแนวทางที่ละเอียดยิ่งขึ้นในการสร้างและโฮสต์แอป ตัวอย่างเช่นเราสามารถตั้งค่างานแยกต่างหากที่เรียกว่า validate ที่เรียกใช้ lint และ test งาน หรือเราอาจมี host งานที่รัน server และ watch. ความสามารถในการจัดระเบียบงานนี้มีประสิทธิภาพมากโดยเฉพาะอย่างยิ่งเมื่อแอปพลิเคชันของคุณปรับขนาดและต้องการงานอัตโนมัติมากขึ้น

การพัฒนาเทียบกับการสร้างการผลิต

if (argv.prod) { process.env.NODE_ENV = 'production'; } let PROD = process.env.NODE_ENV === 'production';

การใช้ yargs ไลบรารี NPM เราสามารถจัดหาแฟล็กบรรทัดคำสั่งให้กับ Gulp ที่นี่ฉันสั่งให้ gulpfile ตั้งค่าสภาพแวดล้อมโหนดเป็นใช้งานจริงถ้า --prod ถูกส่งไปที่ gulp ในเทอร์มินัล ของเรา PROD จากนั้นจะใช้ตัวแปรเป็นเงื่อนไขเพื่อแยกความแตกต่างของพัฒนาการและพฤติกรรมการผลิตใน gulpfile ของเรา ตัวอย่างเช่นหนึ่งในตัวเลือกที่เราส่งต่อไปยัง browserify ของเรา config คือ:

plugin: PROD ? [] : [hmr, watchify]

สิ่งนี้บอก browserify เพื่อไม่ใช้ปลั๊กอินใด ๆ ในโหมดการผลิตและใช้ hmr และ watchify ปลั๊กอินในสภาพแวดล้อมอื่น ๆ

นี้ PROD conditional มีประโยชน์มากเพราะช่วยให้เราไม่ต้องเขียน gulpfile แยกต่างหากสำหรับการผลิตและการพัฒนาซึ่งท้ายที่สุดจะมีการซ้ำโค้ดจำนวนมาก แต่เราสามารถทำสิ่งต่างๆเช่น gulp --prod เพื่อรันงานเริ่มต้นในการผลิตหรือ gulp html --prod เพื่อเรียกใช้ html งานในการผลิต ในทางกลับกันเราเห็นก่อนหน้านี้ว่าทิ้งขยะไปป์ไลน์ของเราด้วยข้อความเช่น .pipe(cond(!PROD, livereload())) ไม่ได้อ่านมากที่สุด ในท้ายที่สุดมันก็ขึ้นอยู่กับความชอบว่าคุณต้องการใช้วิธีการตัวแปรบูลีนหรือตั้งค่าสอง gulpfiles แยกกัน

ตอนนี้เรามาดูกันว่าจะเกิดอะไรขึ้นเมื่อเรายังคงใช้ Gulp เป็นตัวเรียกใช้งาน แต่แทนที่ Browserify ด้วย Webpack

วิธีการสร้างกองทุนรวมการลงทุนด้านอสังหาริมทรัพย์

การตั้งค่าอึก + Webpack

ทันใดนั้น gulpfile ของเรามีความยาวเพียง 99 บรรทัดโดยมีการนำเข้า 12 ครั้งซึ่งค่อนข้างลดลงจากการตั้งค่าก่อนหน้านี้! หากเราตรวจสอบงานเริ่มต้น:

gulp.task('default', (cb) => { runSequence('lint', 'test', 'build', 'server', 'watch', cb); });

ตอนนี้การตั้งค่าแอปพลิเคชันเว็บเต็มรูปแบบของเราต้องการเพียงห้างานแทนที่จะเป็นเก้าอย่างซึ่งเป็นการปรับปรุงอย่างมาก

นอกจากนี้เรายังไม่จำเป็นต้องมี livereload ของเรา watch ตอนนี้งานเป็นเพียง:

gulp.task('watch', () => { gulp.watch(config.paths.js, () => { runSequence('lint', 'test'); }); });

ซึ่งหมายความว่าผู้เฝ้าดูอึกทึกของเราไม่ได้กระตุ้นให้เกิดพฤติกรรมการคืนเงินทุกประเภท เราไม่จำเป็นต้องโอน index.html เพื่อเป็นโบนัสเพิ่มเติม จาก app ถึง dist หรือ build อีกต่อไป.

กลับโฟกัสของเราไปที่การลดภารกิจ html, css, js ของเรา และ fonts งานทั้งหมดถูกแทนที่ด้วย build งาน:

gulp.task('build', () => { runSequence('clean', 'html'); return gulp.src(config.paths.entry) .pipe(webpack(require('./webpack.config'))) .pipe(gulp.dest(config.paths.baseDir)); });

ง่ายพอ เรียกใช้ clean และ html งานตามลำดับ เมื่อเสร็จแล้วให้จับจุดเข้าใช้งานของเราไปป์ผ่าน Webpack ผ่าน webpack.config.js ไฟล์เพื่อกำหนดค่าและส่งบันเดิลผลลัพธ์ไปยัง baseDir ของเรา (อย่างใดอย่างหนึ่ง dist หรือ build ขึ้นอยู่กับโหนด env)

มาดูไฟล์กำหนดค่า Webpack:

webpack.config.js

นี่เป็นไฟล์กำหนดค่าที่ค่อนข้างใหญ่และน่ากลัวดังนั้นเรามาอธิบายคุณสมบัติที่สำคัญบางอย่างที่ตั้งค่าไว้ใน module.exports ของเรา วัตถุ.

devtool: PROD ? 'source-map' : 'eval-source-map',

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

entry: PROD ? './app/index' : [ 'webpack-hot-middleware/client?reload=true', // reloads the page if hot module reloading fails. './app/index' ]

นี่คือจุดเข้าบันเดิลของเรา สังเกตว่ามีการส่งอาร์เรย์ซึ่งหมายความว่ามีจุดเข้าใช้งานหลายจุด ในกรณีนี้เรามีจุดเริ่มต้นที่คาดหวัง app/index.js เช่นเดียวกับ webpack-hot-middleware จุดเริ่มต้นที่ใช้เป็นส่วนหนึ่งของการตั้งค่าการโหลดโมดูลใหม่

output: { path: PROD ? __dirname + '/build' : __dirname + '/dist', publicPath: '/', filename: 'bundle.js' },

นี่คือที่ที่จะแสดงบันเดิลที่คอมไพล์ ตัวเลือกที่สับสนที่สุดคือ publicPath ตั้งค่า URL พื้นฐานสำหรับตำแหน่งที่บันเดิลของคุณจะโฮสต์บนเซิร์ฟเวอร์ ตัวอย่างเช่นถ้าคุณ publicPath คือ /public/assets จากนั้นกลุ่มจะปรากฏใต้ /public/assets/bundle.js บนเซิร์ฟเวอร์

devServer: { contentBase: PROD ? './build' : './app' }

สิ่งนี้จะบอกเซิร์ฟเวอร์ว่าจะใช้โฟลเดอร์ใดในโครงการของคุณเป็นไดเรกทอรีรากของเซิร์ฟเวอร์

หากคุณเคยสับสนเกี่ยวกับวิธีที่ Webpack แมปบันเดิลที่สร้างขึ้นในโปรเจ็กต์ของคุณกับบันเดิลบนเซิร์ฟเวอร์โปรดจำสิ่งต่อไปนี้:

  • path + filename: ตำแหน่งที่แน่นอนของบันเดิลในซอร์สโค้ดโครงการของคุณ
  • contentBase (ในฐานะรูท /) + publicPath: ตำแหน่งของบันเดิลบนเซิร์ฟเวอร์
plugins: PROD ? [ new webpack.optimize.OccurenceOrderPlugin(), new webpack.DefinePlugin(GLOBALS), new ExtractTextPlugin('bundle.css'), new webpack.optimize.DedupePlugin(), new webpack.optimize.UglifyJsPlugin({compress: {warnings: false}}) ] : [ new webpack.HotModuleReplacementPlugin(), new webpack.NoErrorsPlugin() ],

นี่คือปลั๊กอินที่ช่วยเพิ่มประสิทธิภาพการทำงานของ Webpack ในทางใดทางหนึ่ง ตัวอย่างเช่น webpack.optimize.UglifyJsPlugin เป็นผู้รับผิดชอบในการลดขนาด

loaders: [ {test: /.js$/, include: path.join(__dirname, 'app'), loaders: ['babel']}, { test: /.css$/, loader: PROD ? ExtractTextPlugin.extract('style', 'css?sourceMap'): 'style!css?sourceMap' }, { test: /.scss$/, loader: PROD ? ExtractTextPlugin.extract('style', 'css?sourceMap!resolve-url!sass?sourceMap') : 'style!css?sourceMap!resolve-url!sass?sourceMap' }, gif)(?S*)?$/, loader: 'url?limit=100000&name=img/[name].[ext]', woff2 ]

เหล่านี้คือรถตัก โดยพื้นฐานแล้วพวกเขาประมวลผลไฟล์ล่วงหน้าที่โหลดผ่าน require() งบ พวกมันค่อนข้างคล้ายกับท่อ Gulp ตรงที่คุณสามารถโซ่รถตักเข้าด้วยกันได้

ลองตรวจสอบวัตถุตัวโหลดของเรา:

{test: /.scss$/, loader: 'style!css?sourceMap!resolve-url!sass?sourceMap'}

test คุณสมบัติบอก Webpack ว่าตัวโหลดที่กำหนดจะใช้ถ้าไฟล์ตรงกับรูปแบบ regex ที่ระบุในกรณีนี้ /.scss$/ loader คุณสมบัติสอดคล้องกับการกระทำที่ตัวโหลดดำเนินการ ที่นี่เราเชื่อมโยงกัน style, css, resolve-url และ sass รถตักซึ่งดำเนินการในลำดับย้อนกลับ

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

index.js

import React from 'react'; import {render} from 'react-dom'; import {Router, browserHistory} from 'react-router'; import routes from './routes'; // CSS imports import '../node_modules/bootstrap/dist/css/bootstrap.css'; import '../node_modules/font-awesome/css/font-awesome.css'; import './styles/global.scss'; render(, document.getElementById('app'));

ในทำนองเดียวกันในองค์ประกอบส่วนหัวของเราเราสามารถเพิ่ม import './Header.scss' เพื่อนำเข้าสไตล์ชีตที่เกี่ยวข้องของคอมโพเนนต์ นอกจากนี้ยังใช้กับส่วนประกอบอื่น ๆ ทั้งหมดของเรา

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

เพื่อให้สรุปสั้น ๆ ว่าคุณลักษณะนี้ทำงานอย่างไร: Webpack จะแทรก CSS ลงในบันเดิล JS ของเรา ในความเป็นจริง Webpack สามารถทำได้สำหรับรูปภาพและแบบอักษรเช่นกัน:

gif)(?S*)?$/, loader: 'url?limit=100000&name=img/[name].[ext]', ttf)(?S*)?$/, loader: 'url?limit=100000&name=fonts/[name].[ext]'

ตัวโหลด URL สั่งให้ Webpack แทรกรูปภาพและฟอนต์ของเราเป็น URL ข้อมูลหากมีขนาดไม่เกิน 100 KB มิฉะนั้นจะใช้เป็นไฟล์แยกกัน แน่นอนว่าเราสามารถกำหนดขนาดคัตออฟเป็นค่าอื่นได้เช่น 10 KB

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

การตั้งค่าสคริปต์ Webpack + NPM

ในการตั้งค่านี้เราใช้สคริปต์ npm โดยตรงแทนที่จะใช้ gulpfile ในการทำงานอัตโนมัติ

package.json

'scripts': { 'start': 'npm-run-all --parallel lint:watch test:watch build', 'start:prod': 'npm-run-all --parallel lint test build:prod', 'clean-dist': 'rimraf ./dist && mkdir dist', 'clean-build': 'rimraf ./build && mkdir build', 'clean': 'npm-run-all clean-dist clean-build', 'test': 'mocha ./app/**/*.test.js --compilers js:babel-core/register', 'test:watch': 'npm run test -- --watch', 'lint': 'esw ./app/**/*.js', 'lint:watch': 'npm run lint -- --watch', 'server': 'nodemon server.js', 'server:prod': 'cross-env NODE_ENV=production nodemon server.js', 'build-html': 'node tools/buildHtml.js', 'build-html:prod': 'cross-env NODE_ENV=production node tools/buildHtml.js', 'prebuild': 'npm-run-all clean-dist build-html', 'build': 'webpack', 'postbuild': 'npm run server', 'prebuild:prod': 'npm-run-all clean-build build-html:prod', 'build:prod': 'cross-env NODE_ENV=production webpack', 'postbuild:prod': 'npm run server:prod' }

ในการรันรุ่นการพัฒนาและการผลิตให้ป้อน npm start และ npm run start:prod ตามลำดับ

สิ่งนี้มีขนาดกะทัดรัดกว่า gulpfile ของเราอย่างแน่นอนเนื่องจากเราได้ตัดโค้ด 99 ถึง 150 บรรทัดลงเหลือ 19 NPM scripts หรือ 12 ถ้าเราไม่รวมสคริปต์การผลิต (ซึ่งส่วนใหญ่จะสะท้อนสคริปต์การพัฒนาด้วยสภาพแวดล้อมโหนดที่ตั้งค่าเป็น production ). ข้อเสียเปรียบคือคำสั่งเหล่านี้ค่อนข้างคลุมเครือเมื่อเทียบกับงาน Gulp ของเราและไม่ค่อยแสดงออก ตัวอย่างเช่นไม่มีทาง (อย่างน้อยก็ที่ฉันรู้) ที่จะให้สคริปต์ npm เดียวรันคำสั่งบางคำสั่งในซีรีส์และอื่น ๆ ควบคู่กันไป เป็นอย่างใดอย่างหนึ่ง

อย่างไรก็ตามมีข้อได้เปรียบอย่างมากสำหรับแนวทางนี้ โดยใช้ไลบรารี NPM เช่น mocha โดยตรงจากบรรทัดคำสั่งคุณไม่จำเป็นต้องติดตั้ง Gulp wrapper ที่เท่ากันสำหรับแต่ละตัว (ในกรณีนี้คือ gulp-mocha)

แทนที่จะติดตั้ง NPM

  • บินเอสลินท์
  • อึก - มอคค่า
  • อึก - โนเดมอน
  • ฯลฯ

เราติดตั้งแพ็คเกจต่อไปนี้:

  • สลิง
  • มอคค่า
  • โนเดมอน
  • ฯลฯ

อ้างถึงโพสต์ของ Cory House ทำไมฉันถึงทิ้ง Gulp และ Grunt สำหรับสคริปต์ NPM :

ฉันเป็นแฟนตัวยงของอึก แต่ในโปรเจ็กต์สุดท้ายของฉันฉันจบลงด้วยหลายร้อยบรรทัดใน gulpfile ของฉันและปลั๊กอิน Gulp ประมาณหนึ่งโหล ฉันกำลังดิ้นรนเพื่อรวม Webpack, Browsersync, การโหลดซ้ำแบบร้อน, Mocha และอื่น ๆ อีกมากมายโดยใช้ Gulp ทำไม? ปลั๊กอินบางตัวมีเอกสารไม่เพียงพอสำหรับกรณีการใช้งานของฉัน ปลั๊กอินบางตัวเปิดเผยเฉพาะบางส่วนของ API ที่ฉันต้องการ มีข้อผิดพลาดแปลก ๆ ซึ่งจะดูไฟล์จำนวนเล็กน้อยเท่านั้น สีลอกอีกสีหนึ่งเมื่อส่งออกไปยังบรรทัดคำสั่ง

เขาระบุประเด็นหลักสามประการเกี่ยวกับ Gulp:

วิธีคอมไพล์โค้ด c++
  1. การพึ่งพาผู้เขียนปลั๊กอิน
  2. น่าผิดหวังในการแก้ไขข้อบกพร่อง
  3. เอกสารไม่ปะติดปะต่อ

ฉันมักจะเห็นด้วยกับสิ่งเหล่านี้ทั้งหมด

1. การพึ่งพาผู้เขียนปลั๊กอิน

เมื่อใดก็ตามที่ห้องสมุดเช่น eslint ได้รับการอัปเดตที่เกี่ยวข้อง gulp-eslint ไลบรารีต้องการการอัปเดตที่เกี่ยวข้อง หากผู้ดูแลห้องสมุดสูญเสียความสนใจเวอร์ชันอึกของห้องสมุดจะไม่ซิงค์กับไลบรารีดั้งเดิม เช่นเดียวกับเมื่อสร้างไลบรารีใหม่ ถ้ามีคนสร้างห้องสมุด xyz และมันจับได้ทันใดนั้นคุณต้องมี gulp-xyz ห้องสมุดเพื่อใช้ในงานอึกของคุณ

ในแง่หนึ่งวิธีนี้ไม่ได้ปรับขนาด ตามหลักการแล้วเราต้องการแนวทางเช่น Gulp ที่สามารถใช้ไลบรารีดั้งเดิมได้

2. น่าผิดหวังในการแก้ไขข้อบกพร่อง

แม้ว่าไลบรารีเช่น gulp-plumber ช่วยบรรเทาปัญหานี้ได้มาก แต่อย่างไรก็ตามข้อผิดพลาดในการรายงานใน gulp ก็ไม่เป็นประโยชน์มาก หากแม้แต่ท่อเดียวส่งข้อยกเว้นที่ไม่สามารถจัดการได้คุณจะได้รับสแต็กแทร็กสำหรับปัญหาที่ดูเหมือนว่าไม่เกี่ยวข้องกับสิ่งที่ทำให้เกิดปัญหาในซอร์สโค้ดของคุณ สิ่งนี้สามารถทำให้การแก้ไขจุดบกพร่องกลายเป็นฝันร้ายได้ในบางกรณี ไม่มีจำนวนการค้นหาบน Google หรือ Stack Overflow ที่สามารถช่วยคุณได้หากข้อผิดพลาดนั้นคลุมเครือหรือทำให้เข้าใจผิดเพียงพอ

3. เอกสารไม่ปะติดปะต่อ

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

สรุป

ดูเหมือนชัดเจนสำหรับฉันว่า Webpack เป็นที่ต้องการของ Browserify และสคริปต์ NPM นั้นดีกว่าสำหรับ Gulp แม้ว่าแต่ละตัวเลือกจะมีประโยชน์และข้อเสียก็ตาม Gulp มีความชัดเจนและสะดวกในการใช้งานมากกว่าสคริปต์ NPM แต่คุณจ่ายราคาในสิ่งที่เป็นนามธรรมที่เพิ่มเข้ามาทั้งหมด

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

ที่เกี่ยวข้อง:
  • รักษาการควบคุม: คำแนะนำสำหรับ Webpack และ React, Pt. 1
  • Gulp Under the Hood: การสร้างเครื่องมือทำงานอัตโนมัติบนสตรีม

แนวทางที่ดีกว่าในการปรับใช้ Google Cloud อย่างต่อเนื่อง

เทคโนโลยี

แนวทางที่ดีกว่าในการปรับใช้ Google Cloud อย่างต่อเนื่อง
การประเมินมูลค่าอสังหาริมทรัพย์โดยใช้การวิเคราะห์การถดถอย - บทช่วยสอน

การประเมินมูลค่าอสังหาริมทรัพย์โดยใช้การวิเคราะห์การถดถอย - บทช่วยสอน

กระบวนการทางการเงิน

โพสต์ยอดนิยม
Ractive.js - เว็บแอพที่ทำได้ง่าย
Ractive.js - เว็บแอพที่ทำได้ง่าย
การสอน Mirror API: Google Glass สำหรับนักพัฒนาเว็บ
การสอน Mirror API: Google Glass สำหรับนักพัฒนาเว็บ
ตลาดล้านดอลลาร์ดีกว่าตลาดพันล้านดอลลาร์หรือไม่?
ตลาดล้านดอลลาร์ดีกว่าตลาดพันล้านดอลลาร์หรือไม่?
ทำไมฉันต้องใช้ Node.js การสอนเป็นกรณี ๆ ไป
ทำไมฉันต้องใช้ Node.js การสอนเป็นกรณี ๆ ไป
รองประธานองค์กร
รองประธานองค์กร
 
สงครามเย็นแห่งเทคโนโลยี: ยังคงอยู่ที่นี่และยังคงถูกใช้
สงครามเย็นแห่งเทคโนโลยี: ยังคงอยู่ที่นี่และยังคงถูกใช้
ปรับขนาดด้วยความเร็ว: อธิบายเครือข่ายสายฟ้าของ Bitcoin
ปรับขนาดด้วยความเร็ว: อธิบายเครือข่ายสายฟ้าของ Bitcoin
ส่วนประกอบของปฏิกิริยาที่มีประสิทธิภาพ: คำแนะนำในการเพิ่มประสิทธิภาพการตอบสนอง
ส่วนประกอบของปฏิกิริยาที่มีประสิทธิภาพ: คำแนะนำในการเพิ่มประสิทธิภาพการตอบสนอง
คำแนะนำสำหรับนักพัฒนา Android เกี่ยวกับรูปแบบการเรียกดูตัวอย่างข้อมูล
คำแนะนำสำหรับนักพัฒนา Android เกี่ยวกับรูปแบบการเรียกดูตัวอย่างข้อมูล
การรับรองและการประกันการรับประกัน: เครื่องมือการควบรวมกิจการที่ผู้ขายทุกคนควรทราบ
การรับรองและการประกันการรับประกัน: เครื่องมือการควบรวมกิจการที่ผู้ขายทุกคนควรทราบ
โพสต์ยอดนิยม
  • วิธีการเขียนข้อกำหนดการออกแบบ
  • กระแสเงินสดจากงบกำไรขาดทุน
  • สำหรับสตาร์ทอัพ นักลงทุนที่ซื้อหุ้นในธุรกิจอาจกล่าวได้ดังนี้
  • การออกแบบในงานศิลปะคืออะไร
  • adobe xd ทำอะไร
  • เครื่องมือบรรทัดคำสั่งคืออะไร
หมวดหมู่
  • การทำกำไรและประสิทธิภาพ
  • การออกแบบ Ux
  • เทคโนโลยี
  • การออกแบบตราสินค้า
  • © 2022 | สงวนลิขสิทธิ์

    portaldacalheta.pt