รักษาการควบคุม: A Guide to Webpack and React, Pt. 2
เผยแพร่แล้ว: 2022-03-11ในส่วนแรกของบทช่วยสอน React-Webpack นี้ เราได้พูดถึงวิธีกำหนดค่าตัวโหลดและดำเนินการปรับให้เหมาะสม ตอนนี้ เราจะเข้าสู่เทคนิคขั้นสูงเพิ่มเติมที่เกี่ยวข้องกับกรณีการใช้งานการกำหนดค่า React/Webpack ที่เฉพาะเจาะจง
TypeScript และโต้ตอบกับ Webpack: ป้อน Babel
คุณสามารถใช้ TypeScript ในโครงการ React ได้หลายวิธี แม้ว่า ts-loader
จะเป็นตัวเลือกที่ดี แต่ฉันต้องการเน้นที่วิธีการ transpile TypeScript โดยใช้ @babel/preset-typescript
เนื่องจากห้องสมุดหลายแห่งกำลังเผยแพร่ปลั๊กอิน Babel เพื่อทำการเพิ่มประสิทธิภาพเวลาคอมไพล์ นอกเหนือจากการประมวลผลไฟล์ TypeScript แล้ว ยังช่วยให้เราใช้ปลั๊กอิน Babel ที่จัดเตรียมโดยไลบรารีต่างๆ เช่น styled-components หรือ react-intl
สิ่งแรกที่เราต้องทำคือติดตั้งการพึ่งพา TypeScript และ Babel:
npm install -D typescript @babel/preset-typescript @types/react @types/react-dom
จากนั้นเราจะสร้างไฟล์การกำหนดค่า TypeScript โดยใช้โปรแกรมบรรทัดคำสั่ง tsc
:
./node_modules/.bin/tsc -init --lib dom --jsx react --isolatedModules
คำสั่งด้านบนจะสร้าง tsconfig.json
ที่เหมาะสำหรับการเขียนโค้ดสำหรับสภาพแวดล้อมของเบราว์เซอร์ ตัวเลือก --isolatedModules
บังคับใช้ข้อจำกัดบางประการ ซึ่งทำให้แน่ใจว่าโค้ดที่คุณเขียนจะเข้ากันได้กับ @babel/plugin-transform-typescript
ตัวเลือกนี้มีประโยชน์เพื่อให้ IDE ของคุณเตือนคุณเมื่อคุณกำลังเขียนโค้ดในลักษณะที่ Babel จะไม่สามารถแปลงได้
ต่อไป เราจะอัปเดต babel.config.js
โดยแนะนำพรีเซ็ตใหม่:
@@ -6,7 +6,8 @@ module.exports = { modules: false } ], - "@babel/preset-react" + "@babel/preset-react", + "@babel/preset-typescript" ], plugins: [ "@babel/plugin-transform-runtime",
และเปิดใช้งานนามสกุลไฟล์ .ts
ใน webpack.config.js
:
@@ -11,7 +11,7 @@ module.exports = function(_env, argv) { return { devtool: isDevelopment && "cheap-module-source-map", - entry: "./src/index.js", + entry: "./src/index.tsx", output: { path: path.resolve(__dirname, "dist"), filename: "assets/js/[name].[contenthash:8].js", @@ -20,7 +20,7 @@ module.exports = function(_env, argv) { module: { rules: [ { - test: /\.jsx?$/, + test: /\.(js|jsx|ts|tsx)$/, exclude: /node_modules/, use: { loader: "babel-loader", @@ -61,6 +61,9 @@ module.exports = function(_env, argv) { } ] }, + resolve: { + extensions: [".js", ".jsx", ".ts", ".tsx"] + }, plugins: [ isProduction && new MiniCssExtractPlugin({
การกำหนดค่าข้างต้นก็เพียงพอที่จะสามารถแปลงรหัสของเราได้ แต่ไม่สามารถตรวจสอบได้จริง เราจะต้องดำเนินการตรวจสอบประเภทในกระบวนการคู่ขนานที่แยกจากกันโดยใช้ fork-ts-checker-webpack-plugin
ขั้นแรกเราต้องติดตั้ง:
npm install -D fork-ts-checker-webpack-plugin
จากนั้น เราจะเพิ่มลงในส่วน plugins
ใน webpack.config.js
:
@@ -4,6 +4,7 @@ const HtmlWebpackPlugin = require("html-webpack-plugin"); const webpack = require("webpack"); const TerserWebpackPlugin = require("terser-webpack-plugin"); const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin"); +const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin"); module.exports = function(_env, argv) { const isProduction = argv.mode === "production"; @@ -78,6 +79,9 @@ module.exports = function(_env, argv) { "process.env.NODE_ENV": JSON.stringify( isProduction ? "production" : "development" ) + }), + new ForkTsCheckerWebpackPlugin({ + async: false }) ].filter(Boolean), optimization: {
การระบุ async: false
จะป้องกัน Webpack จากการปล่อยโค้ดที่ไม่ถูกต้อง และแสดงข้อผิดพลาดในการคอมไพล์ในโอเวอร์เลย์เมื่อรันเซิร์ฟเวอร์การพัฒนา
หมายเหตุ: คุณอาจสนใจมาโคร Babel ซึ่งกำลังได้รับความสนใจ
CSS ปรับปรุงผ่าน Webpack
ในบทความที่แล้ว เราได้กล่าวถึงการจัดรูปแบบพื้นฐานโดยใช้ css-loader
มีหลายวิธีในการปรับปรุงการกำหนดค่านี้
การกำหนดค่าที่เสนอจะใช้ประโยชน์จากเทคโนโลยี CSS Modules, Sass และ PostCSS แม้ว่าพวกเขาจะเสริมซึ่งกันและกันในบางวิธี แต่คุณไม่จำเป็นต้องใช้ทั้งหมดพร้อมกัน การตั้งค่าขั้นสุดท้ายจะเปิดใช้งานปลั๊กอินทั้งหมดข้างต้น และเราจะปล่อยให้คุณไม่ต้องดำเนินการใดๆ หากคุณแน่ใจว่า "คุณไม่ต้องการมัน"
โมดูล CSS
โมดูล CSS แก้ปัญหาการกำหนดขอบเขตส่วนกลางในไฟล์ CSS โดยการสร้างชื่อที่ไม่ซ้ำกันแบบสุ่มสำหรับแต่ละคลาส CSS จากมุมมองของไฟล์ JavaScript ที่ใช้โมดูล CSS การเชื่อมโยงระหว่างชื่อคลาสดั้งเดิมกับชื่อคลาสแบบสุ่มจะแสดงโดยอ็อบเจ็กต์ที่ส่งออกโดยตัวโหลด ช่วยให้คุณค้นหาและใช้คลาสที่ระบุในไฟล์ CSS ในลักษณะที่ทำให้การชนกันโดยไม่ได้ตั้งใจแทบจะเป็นไปไม่ได้เลย
การสนับสนุนโมดูล CSS นั้นรวมอยู่ใน css-loader
แล้ว ตอนนี้เราจะต้องเพิ่มกฎใหม่เพื่อให้ชัดเจนว่ามีการใช้โมดูล CSS เมื่อใด:
@@ -33,11 +33,25 @@ module.exports = function(_env, argv) { }, { test: /\.css$/, use: [ isProduction ? MiniCssExtractPlugin.loader : "style-loader", "css-loader" ] }, + { + test: /\.module.css$/, + use: [ + isProduction ? MiniCssExtractPlugin.loader : "style-loader", + { + loader: "css-loader", + options: { + modules: true + } + } + ] + }, { test: /\.(png|jpg|gif)$/i, use: {
ด้วยเหตุนี้ ไฟล์ใดๆ ที่ลงท้ายด้วย . .module.css
จะถูกประมวลผลโดยเปิดใช้งาน CSS Modules
PostCSS
PostCSS เป็นเฟรมเวิร์กการประมวลผล CSS ที่ขยายได้พร้อมไลบรารีปลั๊กอินขนาดใหญ่ที่คุณสามารถใช้เพื่อขยายไวยากรณ์ CSS ดำเนินการปรับให้เหมาะสม หรือจัดเตรียมทางเลือกสำรองสำหรับเบราว์เซอร์รุ่นเก่า
ขั้นแรก เราจะติดตั้งการพึ่งพาที่จำเป็น:
npm install -D postcss-loader postcss-import postcss-preset-env
และอัปเดตการกำหนดค่า CSS ของเรา:
@@ -47,9 +47,11 @@ module.exports = function(_env, argv) { { loader: "css-loader", options: { - modules: true + modules: true, + importLoaders: 1 } - } + }, + "postcss-loader" ] }, {
เราจะกำหนดค่า PostCSS โดยใช้ปลั๊กอินต่อไปนี้:
-
postcss-import
: เปิดใช้งาน PostCSS เพื่อประมวลผลคำสั่ง@import
-
postcss-preset-env
: ใช้ polyfills เพื่อรองรับคุณสมบัติ CSS ที่ทันสมัยในเบราว์เซอร์ส่วนใหญ่
สร้างไฟล์ชื่อ postcss.config.js
และใส่ข้อมูลดังต่อไปนี้:
module.exports = { plugins: { "postcss-import": {}, "postcss-preset-env": {} } };
คุณสามารถตรวจสอบไดเร็กทอรีปลั๊กอิน PostCSS สำหรับส่วนขยายอื่นๆ ที่คุณอาจพบว่ามีประโยชน์และเพิ่มลงในการกำหนดค่าของคุณ

Sass/SCSS
Sass เป็นอีกหนึ่งเฟรมเวิร์กการประมวลผล CSS ยอดนิยม Sass มาพร้อมกับ "แบตเตอรี่" ซึ่งแตกต่างจาก PostCSS นอกกรอบ Sass ให้การสนับสนุนกฎที่ซ้อนกัน มิกซ์อิน และกฎการเขียนซ้ำสำหรับความเข้ากันได้แบบย้อนหลัง แม้ว่า PostCSS มีเป้าหมายที่จะรักษารูปแบบ CSS มาตรฐานไว้ แต่รูปแบบ Sass อาจแตกต่างจากข้อกำหนด CSS อย่างไรก็ตาม Sass เป็นโซลูชันที่แพร่หลายซึ่งใช้สำหรับเขียน CSS อาจเป็นตัวเลือกที่ง่ายกว่า—แต่ตัวเลือกนั้นขึ้นอยู่กับความต้องการของคุณ
ขั้นแรก เราจะติดตั้งการพึ่งพาที่จำเป็น:
npm install -D sass-loader node-sass resolve-url-loader
จากนั้น เพิ่มตัวโหลดใหม่ในการกำหนดค่า Webpack ของเรา:
@@ -38,6 +38,25 @@ module.exports = function(_env, argv) { "css-loader" ] }, + { + test: /\.s[ac]ss$/, + use: [ + isProduction ? MiniCssExtractPlugin.loader : "style-loader", + { + loader: "css-loader", + options: { + importLoaders: 2 + } + }, + "resolve-url-loader", + { + loader: "sass-loader", + options: { + sourceMap: true + } + } + ] + }, { test: /\.(png|jpg|gif)$/i, use: {
เราได้แก้ไขปัญหาสองสามอย่างเกี่ยวกับข้อมูลโค้ดด้านบนนี้ไว้ก่อนแล้ว:
เราแนะนำ
resolve-url-loader
หลังsass-loader
เพื่อให้การนำเข้าแบบสัมพันธ์ทำงานได้จากไฟล์@import
ed Sassเราระบุตัวเลือก
importLoaders
สำหรับcss-loader
เพื่อประมวลผลไฟล์@import
-ed โดยใช้ตัวโหลดที่ตามมา
ด้วยการกำหนดค่าข้างต้น เราสามารถเริ่มเขียนสไตล์ของเราโดยใช้ Sass/SCSS นอกเหนือจากโมดูล PostCSS และ CSS ที่เราได้อธิบายไว้ก่อนหน้านี้ แม้ว่าตัวเลือกเหล่านี้ทั้งหมดสามารถเปิดใช้งานพร้อมกันได้ แต่คุณไม่จำเป็นต้องใช้ทั้งหมดภายในโปรเจ็กต์เดียวกัน ดังนั้นคุณสามารถเลือกเครื่องมือเดียวที่เหมาะกับความต้องการของคุณมากที่สุด
พนักงานเว็บ
คนงานเว็บ เป็นแนวคิดที่มีประสิทธิภาพของเว็บสมัยใหม่ ช่วยให้คุณถ่ายการคำนวณที่มีราคาแพงออกจากเธรดหลักได้ ควรใช้ผู้ปฏิบัติงานเว็บเท่าที่จำเป็นและสงวนไว้สำหรับสิ่งที่ไม่สามารถเพิ่มประสิทธิภาพได้ด้วยการจัดกำหนดการอัจฉริยะภายในวนรอบเหตุการณ์ การใช้ผู้ปฏิบัติงานเว็บเป็นตัวเลือกที่ดีสำหรับการเพิ่มประสิทธิภาพการทำงานแบบซิงโครนัสที่ยาวนาน
Webpack ทำให้ง่ายต่อการใช้งานเว็บผู้ปฏิบัติงานด้วย worker-loader
ซึ่งรวมไฟล์ของผู้ปฏิบัติงานไว้ในไดเร็กทอรีเอาต์พุตและจัดเตรียมคลาสผู้ปฏิบัติงานให้กับไฟล์ผู้บริโภค
ขั้นแรก เราต้องติดตั้ง worker-loader
:
npm install -D worker-loader
จากนั้นเพิ่มลงในไฟล์กำหนดค่าของเรา:
@@ -31,6 +31,10 @@ module.exports = function(_env, argv) { } } }, + { + test: /\.worker\.js$/, + loader: "worker-loader" + }, { test: /\.css$/, use: [
ตอนนี้ สิ่งที่คุณต้องทำเพื่อเริ่มใช้งานเว็บเวิร์กเกอร์คือสร้างอินสแตนซ์ของคลาสที่นำเข้าจากไฟล์ที่ลงท้ายด้วย . .worker.js
ที่ใช้ Worker API แบบธรรมดา
พนักงานบริการ
เจ้าหน้าที่บริการเปิดใช้งานเทคนิคการเพิ่มประสิทธิภาพขั้นสูงและการปรับปรุงประสบการณ์ผู้ใช้ พวกเขาให้แอปของคุณทำงานแบบออฟไลน์เมื่อผู้ใช้ขาดการเชื่อมต่อเครือข่าย พวกเขายังให้แอปของคุณโหลดได้ทันทีแม้หลังจากกดอัปเดต
Webpack ทำให้ง่ายต่อการกำหนดค่าพนักงานบริการสำหรับแอปของคุณโดยใช้โมดูล workbox-webpack-plugin ขั้นแรกเราต้องติดตั้ง:
npm install -D workbox-webpack-plugin
จากนั้น เราจะเพิ่มปลั๊กอินในส่วน plugins
ของการกำหนดค่า Webpack ของเรา:
@@ -4,6 +4,7 @@ const HtmlWebpackPlugin = require("html-webpack-plugin"); const webpack = require("webpack"); const TerserWebpackPlugin = require("terser-webpack-plugin"); const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin"); +const WorkboxPlugin = require("workbox-webpack-plugin"); module.exports = function(_env, argv) { const isProduction = argv.mode === "production"; @@ -75,6 +76,11 @@ module.exports = function(_env, argv) { "process.env.NODE_ENV": JSON.stringify( isProduction ? "production" : "development" ) + }), + new WorkboxPlugin.GenerateSW({ + swDest: "service-worker.js", + clientsClaim: true, + skipWaiting: true }) ].filter(Boolean), optimization: {
การกำหนดค่าข้างต้นใช้ตัวเลือกต่อไปนี้:
-
swDest
ระบุชื่อไฟล์เอาต์พุตสำหรับไฟล์ผู้ปฏิบัติงานที่สร้างขึ้น -
clientsClaim
แนะนำให้พนักงานบริการควบคุมเพจทันทีหลังจากการลงทะเบียน และเริ่มให้บริการทรัพยากรที่แคชไว้ แทนที่จะรอการโหลดหน้าถัดไป -
skipWaiting
ทำให้การอัปเดตพนักงานบริการมีผลทันที แทนที่จะรอให้อินสแตนซ์ที่ใช้งานอยู่ทั้งหมดถูกทำลาย
มีเหตุผลที่ดีว่าทำไมสองตัวเลือกหลังจึงไม่ใช่ค่าเริ่มต้น เมื่อเปิดใช้งานพร้อมกัน จะมีโอกาสเกิดข้อผิดพลาดในสถานการณ์ที่มีความอ่อนไหวด้านเวลา ดังนั้นจึงขึ้นอยู่กับคุณที่จะตัดสินใจว่าจะเปิดใช้งานตัวเลือกเหล่านั้นในการกำหนดค่าของคุณหรือไม่
สุดท้าย เราต้องลงทะเบียนพนักงานบริการเมื่อผู้ใช้เปิดแอปของเรา:
@@ -2,3 +2,9 @@ import React from "react"; import ReactDOM from "react-dom"; ReactDOM.render(<h3>React App</h3>, document.getElementById("root")); + +if ("serviceWorker" in navigator) { + window.addEventListener("load", () => { + navigator.serviceWorker.register("/service-worker.js"); + }); +}
พนักงานบริการมีความสามารถมากกว่าการเพิ่มความสามารถแบบออฟไลน์ให้กับแอปของเรา หากคุณต้องการการควบคุมพฤติกรรมของพนักงานบริการในระดับที่สูงขึ้น คุณอาจใช้ปลั๊กอิน InjectManifest
แทน ด้วยการเขียนไฟล์พนักงานบริการของคุณเอง คุณยังสามารถเปิดใช้งานการแคชสำหรับคำขอ API และใช้คุณลักษณะอื่นๆ ที่เปิดใช้งานโดยพนักงานบริการ เช่น การแจ้งเตือนแบบพุช คุณสามารถหาข้อมูลเพิ่มเติมเกี่ยวกับความสามารถของ Workbox ได้ในส่วน Advanced Recipes ของเอกสารอย่างเป็นทางการ
Advanced React Webpack Config: มอบความได้เปรียบให้กับโปรเจกต์ของคุณ
ส่วนที่สองของชุดการสอน Webpack ของเราควรให้ความรู้ที่จำเป็นแก่คุณในการขยายการกำหนดค่า Webpack ของคุณ ให้พ้นกรณีการใช้งาน React ทั่วไปส่วนใหญ่ ฉันหวังว่าคุณจะพบว่าข้อมูลนี้มีประโยชน์ และคุณสามารถขยายการกำหนดค่าส่วนบุคคลของคุณได้อย่างมั่นใจ เพื่อให้บรรลุเป้าหมายเฉพาะสำหรับโครงการของคุณ
เช่นเคย คุณสามารถค้นหาไฟล์การกำหนดค่าทั้งหมดบน GitHub และดูเอกสารประกอบของ Webpack และส่วนปลั๊กอินเพื่อค้นหาสูตรเพิ่มเติมที่เกี่ยวข้องกับเป้าหมายของคุณ ขอบคุณสำหรับการอ่าน!