今年三月份入職以來,一直在做後臺運營系統,其中重複性工作有很多,其中元件庫就是一項。儘管現階段有很多優秀的開源元件庫,但是為了適應產品奇奇怪怪的需求,還是要手動實現一些元件。將其沉澱下來,積累一些自己東西。
概述:首先基於Vue-cli腳手架改裝一個元件庫的基本構建工具,它具備以下幾點功能:
- webpack3.0 升級 webpack4.0 => 更好地完成元件的開發以及打包工作;
- 支援sass => 加速元件樣式開發;
- 支援匯入markdown以及markdown樣式自定義、以及code高亮;
- 自動配置路由。
2018年12月25日新增
- highlight打包過大,縮減語言包;
- jscpd檢查重複程式碼。
將之前的v-highlight
指令
// 這樣載入了highlight所有的程式碼語言包,有300kb+
import hljs from 'highlight.js'
import 'highlight.js/styles/vs2015.css'
hljs.configure({ useBR: true })
Vue.directive('highlight',function (el) {
let blocks = el.querySelectorAll('code')
blocks.forEach(block => {
hljs.highlightBlock(block)
})
})
複製程式碼
修改為
import hljs from 'highlight.js/lib/highlight';
import 'highlight.js/styles/github.css';
// 只載入Html、JavaScript
import javascript from 'highlight.js/lib/languages/javascript';
import xml from 'highlight.js/lib/languages/xml';
hljs.registerLanguage('javascript', javascript);
hljs.registerLanguage('xml', xml);
Vue.directive('highlight', function (el) {
let blocks = el.querySelectorAll('code')
Array.prototype.forEach.call(blocks, block => {
hljs.highlightBlock(block)
})
})
複製程式碼
安裝jscpd,npm i --save-dev jscpd
,修改packjson.json
{
....
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
// 新增
"check": "jscpd src",
"build": "node build/build.js"
},
...
}
複製程式碼
執行結果
1. 例項
例項地址:Fat-Ge UI library
程式碼地址:UI-Library code
2. 安裝流程
環境:win-64位、node-v8.12.0
-
安裝
npm install --global vue-cli
安裝vue-cli,之後建立一個ui-library的專案
vue init webpack ui-library
建立的專案的package.json中,webpack的版本為3.6.0
"webpack": "^3.6.0", "webpack-bundle-analyzer": "^2.9.0", "webpack-dev-server": "^2.9.1", "webpack-merge": "^4.1.0" 複製程式碼
為了升級webpack4.1.2,先把當前webpack以及其相關依賴uninstall
npm uninstall -D webpack webpack-bundle-analyzer webpack-dev-server webpack-merge npm uninstall -D copy-webpack-plugin css-loader eslint-loader file-loader html-webpack-plugin url-loader friendly-errors-webpack-plugin optimize-css-assets-webpack-plugin uglifyjs-webpack-plugin vue-loader 複製程式碼
安裝webpack4,由於webpack4依賴webpack-cli,所以也需要安裝
npm install -D webpack webpack-cli webpack-bundle-analyzer webpack-dev-server webpack-merge npm install -D copy-webpack-plugin css-loader eslint-loader file-loader html-webpack-plugin url-loader friendly-errors-webpack-plugin optimize-css-assets-webpack-plugin uglifyjs-webpack-plugin vue-loader 複製程式碼
手動替換
extract-text-webpack-plugin
外掛npm uninstall -D extract-text-webpack-plugin
替換為npm install -D mini-css-extract-plugin
安裝sass相關依賴
npm install -D node-sass sass-loader --save-dev
-
配置
-
首先配置webpack的mode,在webpack.dev.conf.js以及webpack.prod.conf.js中分別加上
const devWebpackConfig = merge(baseWebpackConfig, { mode: 'production', ... }) 複製程式碼
const webpackConfig = merge(baseWebpackConfig, { mode: 'development', ... }) 複製程式碼
-
配置webpack.base.conf.js檔案
// 引入VueLoaderPlugin const { VueLoaderPlugin } = require('vue-loader') // 新增至 const devWebpackConfig = merge(baseWebpackConfig, { ... plugins: [ new VueLoaderPlugin(), ... ] }) 複製程式碼
-
配置webpack.prod.conf.js檔案
需要刪除
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
之後配置config項
const ExtractTextPlugin = require('extract-text-webpack-plugin') const { VueLoaderPlugin } = require('vue-loader') const webpackConfig = merge(baseWebpackConfig, { optimization: { splitChunks: { cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, chunks: 'initial', name: 'vendors', }, 'async-vendors': { test: /[\\/]node_modules[\\/]/, minChunks: 2, chunks: 'async', name: 'async-vendors' } } }, runtimeChunk: { name: 'runtime' } }, plugins: [ // 新增VueLoaderPlugin new VueLoaderPlugin(), ... // 引入MiniCssExtractPlugin new MiniCssExtractPlugin({ filename: utils.assetsPath('css/[name].[contenthash:7].css') }), // Compress extracted CSS. We are using this plugin so that possible // duplicated CSS from different components can be deduped. new OptimizeCSSPlugin({ cssProcessorOptions: config.build.productionSourceMap ? { safe: true, map: { inline: false } } : { safe: true } }), // see https://github.com/ampedandwired/html-webpack-plugin new HtmlWebpackPlugin({ filename: config.build.index, template: 'index.html', inject: true, minify: { removeComments: true, collapseWhitespace: true, removeAttributeQuotes: true // more options: // https://github.com/kangax/html-minifier#options-quick-reference }, // necessary to consistently work with multiple chunks via CommonsChunkPlugin chunksSortMode: 'dependency' }), // keep module.id stable when vendor modules does not change new webpack.HashedModuleIdsPlugin(), // copy custom static assets new CopyWebpackPlugin([ { from: path.resolve(__dirname, '../static'), to: config.build.assetsSubDirectory, ignore: ['.*'] } ]) ] 複製程式碼
-
修改utils.js
exports.cssLoaders = function(options) { options = options || {} // generate loader string to be used with extract text plugin function generateLoaders(loader, loaderOptions) { let loaders = [] if (loader) { loaders = [{ loader: loader + '-loader', options: Object.assign({}, loaderOptions, { sourceMap: options.sourceMap }) }] } if (options.extract) { let extractLoader = { loader: MiniCssExtractPlugin.loader, options: {} } return [extractLoader, 'css-loader'].concat(['postcss-loader'], loaders) } else { return ['vue-style-loader', 'css-loader'].concat(['postcss-loader'], loaders) } } return { css: generateLoaders(), postcss: generateLoaders(), less: generateLoaders('less'), sass: generateLoaders('sass', { indentedSyntax: true }), scss: generateLoaders('sass'), stylus: generateLoaders('stylus'), styl: generateLoaders('stylus') } } 複製程式碼
-
引入
sass-resources-loader
處理公共css檔案npm install -D sass-resources-loader --save-dev
修改上述
return
的值為{ ... scss: generateLoaders('sass').concat({ loader: 'sass-resources-loader', options: { resources: path.resolve(__dirname, '../src/assets/styles/common.scss') } }) ... } 複製程式碼
-
3. 支援匯入markdown以及markdown樣式自定義
由於vue-markdown-loader
與vue-loader版本15有相容性的問題,所以利用text-loader
將Markdown文件匯入並生成String,再編譯為markdown文件。
首先npm install -D text-loader
安裝text-loader,用來引入*.md檔案,再修改webpack.base.conf.js檔案,新增text-loader
rules: [
...(config.dev.useEslint ? [createLintingRule()] : []),
{
test: /.md$/,
loader: 'text-loader'
},
...
]
複製程式碼
在引入marked
對匯入的String進行編譯
<template>
<div class="markdown-body" v-html="compiledMarkdown" v-highlight></div>
</template>
import markdown from '../../README.md'
import marked from 'marked'
export default {
computed: {
markdowonText () {
// 編譯markdown
return marked(markdown)
}
}
}
複製程式碼
覺得markdown的樣式有些醜,可以匯入github-markdown-css
npm install -D github-markdown-css
對樣式進行修改。如果markdown中存在著某些code,可以通過highlight
進行高亮展示
npm install -D highlight
import hljs from 'highlight.js'
// 調整高亮code的樣式
import 'highlight.js/styles/vs2015.css'
hljs.configure({ useBR: true })
// 註冊一個directive用來新增code高亮
Vue.directive('highlight',function (el) {
let blocks = el.querySelectorAll('code')
blocks.forEach(block => {
hljs.highlightBlock(block)
})
})
複製程式碼
4. 自動配置路由
利用require.context
解析某個目錄下的檔案,將其生成Router的配置
const context = require.context('@/components/', true, /demo\.vue$/)
const componentRouters = context.keys().map(url => {
const start = url.indexOf('/')
const end = url.lastIndexOf('/')
const name = url.substring(start + 1, end)
const path = `/${name}`
return {
name,
path,
component: require(`@/components${path}/demo`).default
}
})
export default new Router({
routes: [
{
path: '/',
name: 'mainPage',
component: mainPage
},
...componentRouters
]
}
)
複製程式碼
往期文章:
- 從零實現Vue的元件庫(零)- 基本結構以及構建工具
- 從零實現Vue的元件庫(一)- Toast 實現
- 從零實現Vue的元件庫(二)- Slider 實現
- 從零實現Vue的元件庫(三)- Tabs 實現
- 從零實現Vue的元件庫(四)- File-Reader 實現
- 從零實現Vue的元件庫(五)- Breadcrumb 實現
- 從零實現Vue的元件庫(六)- Hover-Tip 實現
- 從零實現Vue的元件庫(七)- Message-Box 實現
- 從零實現Vue的元件庫(八)- Input 實現
- 從零實現Vue的元件庫(九)- InputNumber 實現
- 從零實現Vue的元件庫(十)- Select 實現
- 從零實現Vue的元件庫(十一)- Date-picker 實現
- 從零實現Vue的元件庫(十二)- Table 實現
- 從零實現Vue的元件庫(十三)- Pagination 實現
- 從零實現Vue的元件庫(十四)- RadioGroup 實現
- 從零實現Vue的元件庫(十五)- CheckboxGroup 實現
原創宣告: 該文章為原創文章,轉載請註明出處。