Bài 02 – Tích hợp Webpack cho Chrome Extension

Tram Ho

Xin chào mọi người! 👋👋👋

Chào mừng bạn đã đến với series/tutorial Lập trình Chrome extension với Typescript + Vue.js.

Trong bài hôm nay, chúng ta sẽ tiếp tục khắc phục các vấn đề khi build Chrome Extension trong bài trước.

First look

Bài trước, nếu bạn để ý thì sẽ thấy yarn serve, yarn build thực chất là script alias tới vue-cli-service. Vue CLI Service cũng sử dụng webpack nhưng tại thời điểm hiện tại thì việc customize với webpack còn gặp một số vấn đề hạn chế:

  • Multi entrypoints với webpack
  • Config webpack theo document nhưng không nhận config webpack mới

Hy vọng trong thời gian tới chúng ta có thể tùy biến được tốt hơn.

Chúng ta sử dụng vue-cli-service để thực hiện build Vue.js và TypeScript thành js “thuần” một cách rất nhanh chóng. Vậy thì thực sự, vue-cli-service đã làm giúp chúng ta những gì? Dưới đây là một số thứ điển hình:

  1. Compile Vue.js + TypeScript và extract thành file dist/js/app.[hash].js
  2. Compile SASS/CSS và extract thành file dist/css/app.[hash].css
  3. Inject các file JavaScript và CSS sau khi build thành công vào file dist/index.html
  4. Đóng gói các library dùng chung giữa các Vue component vào trong chunk-vendors.[hash].js. Ví dụ như: Vue.js, vue-class-component

Cài đặt dependency

Install Webpack

Chính bởi lẽ hạn chế ở trên nên mình sẽ dùng trực tiếp Webpack mà không còn dùng qua vue-cli-service như trước nữa. Chúng ta cần config một chút với webpack để thực hiện những việc mà vue-cli-service đã làm ở trên. Đồng thời giải quyết các vấn đề đang gặp ở bài trước.

Bây giờ, hãy cùng mình cài đặt phiên bản mới nhất là v4.41.5. Và chúng ta sẽ vẫn tiếp tục cài đặt qua yarn nhé:

Kí tự $ là ký tự nhắc dòng lệnh trên terminal của mình, vui lòng bỏ qua.

Install Loaders for webpack

Do không dùng qua vue-cli-service nên mình sẽ cần cài đặt thêm một số loader để phục vụ việc compile một các file cần thiết như .vue|.ts|.ts|.css|.scss.

Trong đó:

  • vue-loader: compile Vue.js
  • ts-loader: compile code TypeScript
  • css-loader node-sass sass-loader: phục vụ cho việc compile CSS, SASS.

Install Webpack Plugins

Tiếp tục, chúng ta cài đặt thêm webpack plugin cần thiết khác là mini-css-extract-plugin, html-webpack-plugin, copy-webpack-plugincross-env:

Refactor code & folder structure

Sử dụng templates/popup.html

Do không dùng vue-cli-service để build nên thư mục public cũng hơi thừa, mình sẽ chuyển public/index.html tới templates/popup.html, rồi sau đó xóa bỏ folder public không còn cần thiết.

Xóa bỏ thẻ link không dùng trong templates/popup.html, cuối cùng nội dung sẽ như sau:

Update NPM scripts

Các lệnh build, serve cũng được chuyển qua dùng webpack:

Trong đó:

  • webpack -w sẽ thêm file watcher, giúp tự build lại source code mỗi khi file source code bị sửa đổi
  • cross-env giúp mình define environment variable như NODE_ENV

Bây giờ lệnh serve không còn serve web server để chúng ta truy cập qua http://localhost:8080 như trước nữa, mà chỉ là tạo watcher để tự build lại code. Do đó, mình sẽ đổi command alias từ serve thành start.

Refactor folder structure

Vì thông thường, một browser extension có thể có nhiều thành phần chứ không chỉ riêng popup. Để gọn gàng hơn một chút, chúng ta sẽ làm gọn gàng hơn một chút giống Viblo Browser Extension đó là chuyển code của popup vào một folder riêng tên là src/popup. Nhân tiện, chúng ta tạo sẵn một folder src/content-scripts với một file main.ts ở trong với nội dung:

Cấu trúc thư mục src bây giờ sẽ trở thành:

Cấu hình webpack

Tạo file webpack.config.js

Như bạn đã thấy, chúng ta sẽ setup webpack để compile code cho hai thành phần trong extension gồm:

  • src/content-scripts
  • src/popup

Chúng ta cần compile chúng thành 2 file riêng biệt, do đó, mình sẽ cần tạo 2 entrypoint cho webpack. Rất tiếc, webpack chỉ support 1 entrypoint mà thôi. Do đó chúng ta phải config webpack riêng biệt cho từng cái.

Config webpack cho content-scripts

MÌnh sẽ có một bài tiếp theo về các thành phần trong browser extension, cũng như chức năng, tác dụng của chúng để mọi người hiểu nên trong bài này bạn hãy tạm hiểu content-scripts sẽ là các script của mình để thực hiện thao tác với DOM của một trang web bạn đang truy cập. Ví dụ, khi chúng ta vào trang Viblo và muốn đổi background của trang từ trắng sang đen, code xử lý đó sẽ được đặt trong content-scripts và khai báo trong manifest.json để browser thực thi.

Content-scripts của mình cũng khá đơn giản vì chỉ là code TypeScript, dó đó, chúng ta chỉ cần sử dụng babel-loaderts-loader trong webpack là đủ. File cấu hình sẽ như sau:

Tạm thời chúng ta có thể comment dòng số 2 và 6 trong webpack.config.js như này để build thử:

Config webpack cho Popup

Popup thì config nhiều hơn một chút vì nó phải làm khá nhiều thứ với Vue.js, TypeScript, Images, SASS.

Trong đó, mình sử dụng MiniCssExtractPlugin để extract css thành file .css, HtmlPlugin để generate file /popup/index.html (đã inject cả /popup/js/index.js/popup/css/main.css.

Bỏ comment trong webpack.config.js để chúng ta chạy webpack build thử cả popupcontent-scripts:

Như vậy là đã thành công rồi! 😆

Tự động tạo manifest.json và ảnh logo

Tới thời điểm này, còn một vấn đề mà chúng ta chưa giải quyết đó là việc tự động copy file manifest.json, static vào dist sau mỗi lần build source code.

Lần này, chúng ta sẽ dùng copy-webpack-plugin để cấu hình tự động generate manifest.json và copy thư mục static mỗi khi build.

Nếu bạn để ý, hai file config webpack sẽ có ouput folder khác nhau. Với popup thì sẽ là dist/popup còn content-scripts sẽ là dist. Vì các file manifest.jsonstatic cần copy vào root, nên config webpack lần này mình sẽ thêm vào webpack/content-scripts.

Đoạn code trên sử dụng chức năng transform của copy-webpack-plugin, giúp mình chèn tên version mới tại mỗi lần release. Chúng ta chỉ cần return Buffer trong hàm transform là được, còn version mình sẽ lấy từ file package.json cho tiện release.

Thử build lại lần cuối:

Bạn thấy trong log build sẽ có cả manifest.json, static/images/logo-*.png được thêm thành công. Tuy nhiên, khi mở extension thì thấy báo lỗi File Not Found, nguyên nhân do chúng ta đã chuyển file index.html vào trong popup/index nên cấu hình file manifest.json trở thành bị lỗi. Hãy đổi link default_popup: "popup/index.html" rồi build lại là được.

Vậy là các vấn đề đã được giải quyết. Bạn có thể và mở lại extension và vậy thấy nó hoạt động bình thường. 😃 Nếu bạn đang follow theo tut này mà gặp vấn đề nào đó, hãy để lại comment để mình cùng thảo luận nhé. Chúc bạn thành công và hẹn gặp lại ở phần sau!

TL;DR

Link tham khảo:

Nếu bạn thấy series này hay và hữu ích thì đừng quên share, upvote, folow mình để đón đọc các bài viết tiếp theo của mình trên Viblo nhé!

Bạn cũng có thể subscribe các tag về VueTypescript trên Viblo để nhận được nhiều hơn nữa các bài viết mới nhất về các topic này trên Vbilo nhé! Viblo sử dụng các dữ liệu mà bạn folow, quan tâm cho hệ thống gợi ý nên các bạn hãy folow những topic bạn yêu thích để hệ thống recommend thêm nhiều bài hay và bổ ích từ hàng nghìn bài viết trên Viblo mà bạn còn chưa từng đọc!

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo