开发环境
pc环境:windows
webpack:5.3.9
webpack-cli:4.9.1
webpack-dev-server: 4.3.1
【全局安装webpack,webpack-cli,webpack-dev-server】
目录结构
- components ui组件
- docs 文档库
引入方式
全局引入
通过vue.use引入
创建组件
- 在src/components目录下新建A目录,在A目录里面新建A.vue
- 创建index.js,将A.vue导出
注意:name要与组件名称一致,比如A.vue,name也应该是A
import A from './A.vue'
export default A
全局引入
- 在src目录下,新建index.js,通过install方法进行注册
import A from './components/A'
const components = {
A,
}
const install = (Vue) => {
Object.keys(components).map((key) => {
const component = components[key]
Vue.component(component.name, component)
})
}
// auto install
if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue);
}
const HBirthDay = {
install
}
export default HBirthDay
//module.exports.default = module.exports = HBirthDay
打包
这里的打包,我们参考element-ui,通过打包成一个js文件,我们在其他项目里面通过vue.use引入
- webpack.common.js
/**
* 公共配置
*/
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
const webpack = require('webpack')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
output: {
path: path.join(__dirname, 'node_modules/hbirthday'), // 打包生成文件地址
filename: 'HBirthDay.min.js', // 指定输出文件的名称
libraryTarget: 'umd',
library: 'HBirthDay',
umdNamedDefine: true
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: ['@babel/plugin-transform-runtime']
}
},
exclude: /node_modules/ // 不编译node_modules下的文件
},
{
// *.vue
test: /\.vue$/,
loader: 'vue-loader'
},
{
// 图片
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10 * 1024 // 10kb
}
}
},
// {
// test: /\.css$/i,
// use: [MiniCssExtractPlugin.loader,"css-loader"],
// },
{
test: /\.css$/i,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
esModule: false,
publicPath: "../",
}
},
"css-loader",
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
[
'postcss-preset-env',
],
],
},
},
}
]
},
]
},
// 解析路径
resolve: {
// 设置src别名
alias: {
'vue': 'vue/dist/vue.esm.js',
'@': path.resolve(__dirname, 'src'),
},
//后缀名 可以根据需要自由增减
extensions: ['.js', '.vue']
},
plugins: [
new VueLoaderPlugin(),
new MiniCssExtractPlugin({
// 类似于 webpackOptions.output 中的选项
// 所有选项都是可选的
filename: 'assets/css/[name].css',
chunkFilename: 'assets/css/[id].css',
}),
new HtmlWebpackPlugin({
filename: 'index.html', // 生成的文件夹名
template: 'public/index.html', // 模板html
favicon: 'public/favicon.ico', // 图标
}),
new webpack.optimize.ModuleConcatenationPlugin()
]
}
- webpack.dev.js
const webpack = require('webpack')
const path = require('path')
const { merge } = require('webpack-merge')
const common = require('./webpack.common')
module.exports = merge(common, {
mode: 'development',
entry: './src/main.js', // 定义入口文件
devServer: {
contentBase: path.join(__dirname, 'dist'), // 告诉服务器内容的来源。仅在需要提供静态文件时才进行配置
compress: true, // 开启压缩
port: 8081, // 端口
hotOnly: true, // 热模块替换,保存页面状态
hot: true, // 自动刷新
open: false,
historyApiFallback: {
index: '/index.html' //与output的publicPath有关(HTMLplugin生成的html默认为index.html)
},
},
devtool: 'source-map',
plugins: [
new webpack.HotModuleReplacementPlugin(), // 配合 devServer:hot 使用,自动刷新页面
]
})
- webpack.prod.js
const { merge } = require('webpack-merge')
const common = require('./webpack.common')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = merge(common, {
mode: 'production',
entry: './src/index.js', // 定义入口文件
externals: {
vue: {
root: 'Vue',
commonjs: 'vue',
commonjs2: 'vue',
amd: 'vue'
}
},
plugins: [
new CleanWebpackPlugin(),
new CssMinimizerPlugin(),
]
})
- package.json
{
"name": "hbirthday",
"version": "1.0.0",
"description": "生日",
"main": "dist/HBirthDay.min.js",
"scripts": {
"dev": "webpack serve --config webpack.dev.js",
"build": "webpack --config webpack.prod.js"
},
"keywords": [],
"author": "hhh",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.14.3",
"@babel/plugin-transform-runtime": "^7.14.3",
"@babel/preset-env": "^7.14.4",
"@vue/cli-plugin-babel": "^4.5.14",
"babel-loader": "^8.2.2",
"clean-webpack-plugin": "^4.0.0-alpha.0",
"css-loader": "^5.2.6",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.3.1",
"less": "^4.1.1",
"less-loader": "^9.1.0",
"style-loader": "^2.0.0",
"url-loader": "^4.1.1",
"vue-loader": "^15.9.7",
"vue-style-loader": "^4.1.3",
"vue-template-compiler": "^2.6.14",
"webpack": "^5.38.1",
"webpack-cli": "^4.7.2",
"webpack-dev-server": "^3.11.2",
"webpack-merge": "^5.8.0"
},
"dependencies": {
"babel-plugin-components": "^1.0.4",
"chalk": "^4.1.1",
"compression-webpack-plugin": "^9.0.0",
"css-minimizer-webpack-plugin": "^3.1.1",
"fa": "^1.0.1",
"hbirthday": "^1.0.0",
"mini-css-extract-plugin": "^2.4.3",
"path": "^0.12.7",
"postcss-loader": "^6.2.0",
"postcss-preset-env": "^6.7.0",
"vue": "^2.6.14",
"vue-router": "^3.5.1",
"vuex": "^3.6.2"
}
}
全局打包命令
npm run build
使用方式
npm发布
- 任务
- 完成组件库打包,可通过全局引入组件
- 发布到npm公共库,可通过npm方式引入
-
操作步骤
-
在package.json main配置里面写入"dist/HBirthDay.min.js",也就是你刚才打包好的js文件,只一步必须,否则无法引入
-
npm config set registry https://registry.npmjs.org/
-
npm login
-
npm publish
426错误解决 :https://blog.csdn.net/weixin_41697143/article/details/120650358
注意:邮箱必须经过校验,否则会显示登录错误
package.json里面的name在发布时,必须全部小写,不能有大写字母,另外在每次发布需要更改json里面的version,必须与上一次version不一样
- 检验是否发布成功
npm发布成功使用方法
局部引入
- 新建webpack.lib.js文件
const fs = require('fs');
const path = require('path');
const { merge } = require('webpack-merge')
const common = require('./webpack.common')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const join = path.join;
const resolve = (dir) => path.join(__dirname, dir);
/**
* @desc 大写转横杠
* @param {*} str
*/
function upperCasetoLine(str) {
let temp = str.replace(/[A-Z]/g, function (match) {
return "-" + match.toLowerCase();
});
if (temp.slice(0, 1) === '-') {
temp = temp.slice(1);
}
return temp;
}
/**
* @desc 获取组件入口
* @param {String} path
*/
function getComponentEntries(path) {
let files = fs.readdirSync(resolve(path));
const componentEntries = files.reduce((fileObj, item) => {
// 文件路径
const itemPath = join(path, item);
// 在文件夹中
const isDir = fs.statSync(itemPath).isDirectory();
const [name, suffix] = item.split('.');
// 文件中的入口文件
if (isDir) {
fileObj[upperCasetoLine(item)] = resolve(join(itemPath, 'index.js'))
}
// 文件夹外的入口文件
else if (suffix === "js") {
fileObj[name] = resolve(`${itemPath}`);
}
return fileObj
}, {});
return componentEntries;
}
module.exports = merge(common, {
mode: 'production',
entry: getComponentEntries('src/components'),
// 输出配置
output: {
// 文件名称
filename: '[name]/index.js',
path:path.resolve(__dirname,'node_modules/hbirthday/lib'),
umdNamedDefine: true,
// 构建依赖类型
libraryTarget: 'umd',
// 库中被导出的项
libraryExport: 'default',
// 引用时的依赖名
library: 'HBirthDay',
},
externals: {
vue: {
root: 'Vue',
commonjs: 'vue',
commonjs2: 'vue',
amd: 'vue'
}
},
plugins: [
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
// 类似于 webpackOptions.output 中的选项
// 所有选项都是可选的
filename: '[name]/style.css',
chunkFilename: '[id]/[id].css',
}),
new CssMinimizerPlugin(),
// new MiniCssExtractPlugin()
]
})
这个文件的作用是加载每个组件文件夹里面的index.js,把它们放置在lib文件夹下
- 组件库里面index.js
import component1 from './src/component1.vue'
component1.install = function (Vue) {
console.info('component1----install----')
Vue.component(component1.name, component1)
}
export default component1
这里导出install方法,到时我们就可以通过use方法引入,当然还有第二种方式,代码如下:
import A from './A.vue'
export default A
通过这种方式,只能通过Vue.component(componentName, component)方式引入
- package.json增加局部打包命令
"build:lib": "webpack --config webpack.lib.js"
- 结果
我们将所有组件都打包在lib目录下,每一个组件目录下都有一个index.js
- 接下来我们就可以在main.js单独引入这里的文件
注意这里用了use的方法,是因为我们在组件index.js导出时使用了组件.install方法
- 接下来我们转变一下引入方式,改为如下方式
import {component1} from 'hbirthday'
// import '组件对应的css文件'
Vue.use(componnent1)
- 在package.json里面增加babel配置,安装babel-plugin-component插件
"babel": {
"plugins": [
[
"component",
{
"libraryName": "hbirthday"
}
]
]
}
- 结果
文档库
https://gitee.com/huihui11239/doc.git
到这里我们就全部讲完了,现在组件库支持全局引入,局部引入
另外也分别讲了利用webpack从0到1搭建一个vue开发,上线环境