封裝Vue組件並發布到npm(完美解決組件中的靜態文件引用)


不少前端開發者學習到一定階段都會去封裝一些自己的組件並將其開源。筆者在學習過程中發現,發布的資源包基本分為兩類:

  1. 打包發布的資源包
  2. 非打包發布的資源包

那么這兩種方式有何不同呢,他們的使用場景如何,具體的操作步驟又是怎么樣的。本文將基於這兩種發布方式,對比他們的不同,詳解其步驟,並對在封裝vue組件和發布npm依賴過程中所遇到的問題進行歸納和解答。相信對於更加全面的了解前端工程化和npm發布流程會有些許幫助。

本文將涉及到:

待封裝的vue組件(組件)
需引用的第三方依賴(第三方依賴)
測試使用的Vue項目(項目)

為了后文不至混淆,將分別使用括弧中內容指代,請讀者注意區分。

 

(一)打包發布

這種方式是將封裝好的組件最終打包成一個js文件發布。這種方式使得發開和調試時更接近與一個前端項目。但是一旦引用圖片等靜態資源需通過BASE64方式打包到js,而對於字體一類較大的靜態資源則根本無法被引用。

適用范圍:沒有或極少的依賴第三方插件、圖片的組件的封裝或JS方法的封裝

1. 項目結構

使用webpack構建前端工程,此處注意webpack配置文件應當區分開發和打包。base.js、dev.js和build.js通過merge語句鏈接。

// 項目結構 module |——src | |——asset | |——components // 組件包文件夾 | | |——index.js // 組件包打包入口 | | └——componentA.vue // 組件 | |——pages // 供開發時預覽的頁面 | |——router | |——template // html模板 | |——tools | |——app.vue // 供開發時預覽的vue入口 | └——main.js // 供開發時預覽的項目入口 |——webpack // webpack配置文件夾 | |——base.js // 通用配置 | |——dev.js // 開發用配置 | └——build.js // 打包用配置 |——package.json └——README.md

2. 配置webpack

base.js

只放基礎配置如module和通用的plugins,不要包含打包入口,和出口。

dev.js

  1. 需要配置預覽相關的頁面,因此入口應該為最外層main.js,這個入口文件掛在了配置了路由信息的app.vue。
  2. 因為開發環境是起本地服務,因此無需出口信息。
  3. 同時需要配置htmlWebpackPlugin和WebpackDevServer服務相關。
var webpack = require('webpack'); config.entry = { app:[path.join(APP_SRC, 'main.js')], vendors: [ 'vue', 'vuex', 'vue-router', 'axios' ] }, config.entry.app.unshift("webpack-dev-server/client?http://localhost:8088/") config.plugins.push(new htmlWebpackPlugin({ hash: true, minify: { removeComments: true, collapseWhitespace: true, }, // favicon: path.join(APP_SRC, '/asset/images/ico.ico'), template: path.join(APP_SRC, '/template/index.html'), })) var compiler = webpack(config); var serve = new WebpackDevServer(compiler, { quiet: false, stats: { colors: true }, compress: true, //gzip壓縮 publicPath: 'http://localhost:8088/', contentBase: '../dist/', //默認情況下,webpack-dev-server會從項目的根目錄提供文件,可以通過此選項設置文件的目錄名 historyApiFallback: true, //當設置為true時,訪問所有服務器上不存在的文件,都會被重定向到/,也就是index.html文件 }).listen(8088);

build.js

  1. 組件的入口為components目錄下的index.js(index.js引入並導出我們需要封裝的組件)。
  2. 出口信息應當包含引包時所使用的名字,組件名不能出現大寫。
var config = require("./base.js"); module.exports = merge(config, { entry: [path.join(APP_SRC, '/components/index.js')], output: { path: APP_DIST, filename: 'index.js', library: 'module_name', // 指定的就是你使用require時的模塊名 libraryTarget: 'umd', // 指定輸出格式 umdNamedDefine: true // 會對 UMD 的構建過程中的 AMD 模塊進行命名。否則就使用匿名的 define }, devtool: false, mode: 'production', });

3. 修改package.json

package.json中需要包含引包的入口,包名稱和版本號。項目在引用組件時會根據main找到組件入口。

{
  "name": "my_module", "version": "1.0.0", "main": "dist/index.js" ... }

4. 組件開發

組件開發無需多說,只要執行npm run dev將所需封裝的組件引入到預覽頁面中開發調試即可。
組件入口component/index.js需引入並導出組件,更加詳細請看下一章節。

5. 打包發布

維護版本

手動修改package.json中的version或者執行npm version patch生成迭代一個版本

執行打包命令

npm run build

登陸npm。

注意這一需要登陸官方倉庫,如果之前連接的是淘寶鏡像需要線切換回來。下面是查看倉庫源和切換倉庫的命令。

npm config get registry  // 查看倉庫源 npm config set registry https://registry.npm.taobao.org npm config set registry http://registry.npmjs.org 

登陸npm,輸入賬號、密碼、郵箱

npm login

發布

npm publish

 

(二)非打包發布

封裝好的組件不經過打包,直接發布,用戶在引用時不是引用一個獨立的js文件,而是用過一個入口文件引用一些列的文件。這種方式因為不是在單獨引用一個js所以可以完美解決第三方插件的引用、圖片、字體等靜態文件的引用但是對於組件項目本身而言開發時的預覽調試方法則需要另尋他路。而且筆者暫時沒有想到不適用測方法的,是筆者認為較為完美的封裝發布方案

1. 項目結構

因為無需打包,因此不再需要webpack配置,項目結構也更加精煉。可以將組件的入口已到根目錄。

// 項目結構 module |——src | |——asset | |——components // 組件包文件夾 | | |——componentA // 組件A | | └——componentB.vue // 組件B | └——tools |——index.js // 組件入口 |——package.json └——README.md

2. package.json

組件的名字、版本、入口文件這三個屬性必備之外,需要注意的是dependencies中記錄的第三方依賴都會在執行npm install的時候被安裝。

{
  "name": "my_module", "version": "1.2.16", "main": "index.js", "dependencies": { "view-design": "^4.0.2", ... } ... }

3. 入口文件(index.js)

引入組件

使用正確的相對路徑將組件和靜態文件引入到index.js

import './src/asset/css/index.less' import ComponentA from './src/components/ComponentA.vue' import ComponentB from './src/components/ComponentB.vue'

導出用於全局安裝的對象

如果你想通過Vue.use(MyComponent)的方式使用組件,需要導出一個包含了所有組件的對象,並給這個對象定義install方法供Vue.use()方法調用。

let ModuleObj = { ComponentA, ComponentB } let MyModule = {} MyModule.install = (Vue) => { for (let i in ModuleObj) { Vue.component(i, ModuleObj[i]) } } export default MyModule

導出多個組件支持按需加載

export { ComponentA, ComponentB }

4. 組件開發

關於引用第三方依賴

以引用iview為例,在組件(components/ComponentA.vue)內部局部注冊iview組件。這樣相當於按需加載有助於減小最終項目打包的體積。

<script> import { Poptip, Dropdown, DropdownMenu, DropdownItem, Icon, Input } from 'view-design'; export default { components: { Poptip, Dropdown, DropdownMenu, DropdownItem, Icon, Input } } </script>

關於引用靜態文件

使用正確的相對路徑引用css、圖片或字體,如果之前習慣使用webpack的alias路徑別名,此時當然也是不生效的。

5. 發布

無需打包,但同樣需要維護版本,直接發布

維護版本

手動修改package.json中的version或者執行npm version patch生成迭代一個版本

登陸發布

npm login npm publish

6. 引用和開發調試

因為組件項目不再有供開發調試的特面,因此需要在引用組件的項目中對組件進行調試,安裝組件之后,在node_module中找到組件的所在的文件夾,進入修改即可完成調試。最后將調試好的組件文件夾拷貝出來,除package.json單獨維護,發布即可。
兩種引用方式:

// 全局安裝 import MyModule from 'my_module' Vue.use(MyModule) // 按需加載 import { ComponentA, ComponentB } from 'my_module' Vue.component('ComponentA', ComponentA) Vue.component('ComponentB', ComponentB)

電腦刺綉綉花廠 http://www.szhdn.com 廣州品牌設計公司https://www.houdianzi.com

(三)總結

  打包發布 非打包發布
webpack 需要配置 無需配置
發布 發布前需要打包 發布前無需打包
引用靜態文件 較小的圖片可以通過BASE64方式打包僅js文件 隨意使用
引用第三方依賴 可以引用,但如果第三方依賴包含較多的靜態文件時可能會出現引用不到的情況 隨意引用
被應用的文件 一個打包好的js 組件的入口文件
調試方法 在組件項目中即可調試 需要在引用組件的項目中的node_module中對用模塊中調試

對比兩種方式,筆者更傾向於后者,但只要理解了前端項目引用依賴的原理就會發現其實兩者本質上都是一樣的,讀者可根據自己的需要選擇一種方式進行封裝。文中如有錯誤也希望各位不吝賜教及時指出。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM