webpack如何打包一個按需引入的vue組件庫
前言
在公司裡一般有多個相同技術棧的項目,畢竟在多個項目間copy公共組件代碼太繁瑣,也不利於組件庫的維護,所以怎麼高效維護一套公共的組件代碼很重要。這種情況,一般我們可以考慮封裝成組件庫,發佈到npm上。在每個項目裡隻需要npm install xxx 即可使用,避免瞭在項目間相互copy。我們這就開始使用webpack打包一個公共的vue組件庫。
在項目中使用vue組件庫的一般姿勢
- 1、通過import引入,並在入口文件main.js裡使用Vue.use方法完成組件的全局註冊,便可在任何單文件組件中直接使用。如下
import Vue from "vue" import App from "./App.vue" import mylib from "mylib" Vue.use(mylib) new Vue({ render: h => h(App) }).$mount("#app");
- 2、上面的方式看似是一勞永逸,可隨著組件庫越發的壯大,會出現我引入瞭整個組件庫代碼,但我在目前的項目裡隻使用瞭其中一小部分組件,但在項目最終打包的時候卻把組件庫裡所有的組件代碼都打包進瞭bundle文件裡,影響瞭最終代碼體積,這明顯是不合理的。所以便有瞭按需引入組件庫的方式,這裡我們參考element-ui的按需引入方式,如下。
接下來,如果你隻希望引入部分組件,比如 Button 和 Select,那麼需要在 main.js 中寫入以下內容:
import Vue from 'vue'; import { Button, Select } from 'element-ui'; import App from './App.vue'; Vue.component(Button.name, Button); Vue.component(Select.name, Select); new Vue({ el: '#app', render: h => h(App) });
為什麼這樣具名導入組件就可以做到按需引入呢?其實是babel-plugin-component插件幫我們完成瞭轉換的工作。在babel-plugin-component內部會把
import { Button, Select } from 'element-ui';
轉換成
var button = require('element-ui/lib/button') var select = require('element-ui/lib/select') require('element-ui/lib/theme-chalk/button/style.css') require('element-ui/lib/theme-chalk/select/style.css')
上面的element-ui是組件庫名,theme-chalk是組件庫樣式所在的文件夾名,都是可以配置的。button、select是組件名,lib是babel-plugin-component插件默認尋找組件的文件夾。
webpack實現可按需引入的組件庫
先npm init創建項目,因為是每個組件單獨打包,所以每個組件都導出一個函數,再Vue.use()的時候執行這個函數,完成組件的全局註冊。項目目錄結構如下
components/navbar/navbar.vue <template> <div class="header__all">{{text}}</div> </template> <script> export default { name: "navbar", props: { text: String } }; </script> <style rel="stylesheet/scss" lang="scss" scoped> .header__all{ background-color: #000000; color: #FFFFFF; display: flex; justify-content: center; align-items: center; height: 50px; width: 100%; } </style>
components/navbar/index.js import navbar from "./navbar.vue"; export default function(Vue) { Vue.component(navbar.name,navbar); }
src/index.js import navbar from "./components/navbar" function install(Vue){ Vue.use(navbar) } if(window && window.Vue) { Vue.use(install) } export default install
接下來就是使用webpack打包
- 第一步:先安裝所有需要用到的依賴
npm i -D webpack webpack-cli babel-loader @babel/core @babel/preset-env babel-plugin-component clean-webpack-plugin css-loader mini-css-extract-plugin node-sass postcss postcss-loader autoprefixer cssnano sass-loader terser-webpack-plugin vue-loader vue-template-compiler
- 第二步:配置webpack.config.js
const path = require('path') const TerserPlugin = require("terser-webpack-plugin"); const { CleanWebpackPlugin } = require("clean-webpack-plugin") const { VueLoaderPlugin } = require('vue-loader') const MiniCssExtractPlugin = require('mini-css-extract-plugin') module.exports = { mode: 'none', entry: { 'navbar': './src/components/navbar/index.js', 'navbar.min': './src/components/navbar/index.js', 'test-lib': './src/index.js', 'test-lib.min': './src/index.js' }, output: { path: path.join(__dirname,"/lib"), filename: '[name].js', libraryTarget: 'umd', library: '[name]', libraryExport: 'default' }, // externals:[], optimization: { minimize: true, minimizer: [ new TerserPlugin({ test: /\.min\.js$/, }), ], }, module: { rules: [ { test: /\.vue$/, use: ['vue-loader'] }, { test: /\.css$/, use: [MiniCssExtractPlugin.loader,'css-loader','postcss-loader'] }, { test: /\.s[ac]ss$/i, use: [MiniCssExtractPlugin.loader,'css-loader','postcss-loader','sass-loader'] }, { test: /\.js$/, exclude: /node_modules/, use:{ loader: 'babel-loader', options: { cacheDirectory: true } } } ] }, plugins: [ new VueLoaderPlugin(), new CleanWebpackPlugin(), new MiniCssExtractPlugin({ filename: 'lib-style/[name].css' }) ] }
- 第三步:更改package.json的main字段,並往scripts裡添加打包命令
"main": "./lib/test-lib.min.js", "scripts": { "build": "webpack --config webpack.config.js" }
- 第四步:執行 npm run build 打包組件庫,成功後項目多瞭個lib文件夾,存放打包後組件庫的代碼。lib文件夾裡每個文件都有一個對應的.min文件,.min文件分別用terser-webpack-plugin插件和cssnano壓縮。
調試組件庫
有兩種方式可調試本地的組件庫
- 新建test.html,然後以
- vuecli新建個測試項目,然後通過npm link的方式鏈接到測試項目中去使用
這裡展示就使用最粗暴的方式一,新建test.html,npm link各位看官老爺可以自己去嘗試下。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <link rel="stylesheet" href="./lib/lib-style/test-lib.min.css" rel="external nofollow" > </head> <body> <div id="app"> <navbar text="header"></navbar> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="./lib/test-lib.min.js"></script> <script> new Vue({ el: '#app' }) </script> </html>
測試結果:
到這一步,至少說明代碼構建沒什麼大問題,但按需引入功能還沒驗收,接下來我們就繼續把組件庫發佈到npm上,完全效仿element-ui的使用方式在vuecli項目中使用,看看實現的效果如何。
npm 發佈
步驟非常簡單,隻需4步
- 在npm官網註冊賬號並驗證郵箱。
- 在命令行中輸入 npm login 完成登錄。
- 如果npm使用的是淘寶鏡像源,需要切回npm源。
- 進入需要發佈的項目目錄執行npm publish 發佈。
完成後,接著就在測試項目裡 npm install 安裝我們自己的組件庫。
調試組件庫按需引入
在測試項目裡的babel.config.js,添加babel-plugin-component配置,並重啟項目。
babel-plugin-component基本配置參考
// babel.config.js module.exports = { presets: ["@vue/cli-plugin-babel/preset"], plugins: [ [ 'component', { libraryName: 'element-ui', styleLibraryName: 'theme-chalk' }, 'element-ui' ], [ 'component', { libraryName: 'test-lib', styleLibrary: { "name": "lib-style", // same with styleLibraryName "base": false // if theme package has a base.css } }, 'test-lib' ], ] };
在test.vue中使用組件庫
<template> <div> <navbar :text="msg"></navbar> <el-button type="primary" class="dg-margin-t-20">element-button</el-button> </div> </template> <script> import Vue from "vue"; import { navbar } from "juejintest-lib"; import { button } from "element-ui"; Vue.use(navbar) Vue.use(button) export default { data:function() { return { msg: 'text' } } }; </script> <style lang="scss"> .dg-margin-t-20{ margin-top:20px; } </style>
到此按需引入的vue組件庫我們就構建完成瞭。文中使用webpack做為構建工具,其實webpack一般都用來構建應用項目,構建公共庫的話,用得更多的是rollup,等我rollup更熟悉的時候再用rollup實現一次,下次見。
總結
到此這篇關於webpack如何打包一個按需引入vue組件庫的文章就介紹到這瞭,更多相關webpack打包按需引入vue組件庫內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- 使用webpack手動搭建vue項目的步驟
- webpack搭建vue環境時報錯異常解決
- 快速創建React項目並配置webpack
- 詳解Vue註冊組件的方法
- 教你使用webpack打包編譯TypeScript代碼