theme: juejin
highlight: tomorrow-night-bright
本文为稀土掘金技术社区首发签约文章,14天内禁止转载,14天后未获授权禁止转载,侵权必究!
近年来,Web Components,也称为自定义元素,已经成为多个浏览器的标准 API,它允许开发人员仅使用 HTML、CSS 、JavaScript 来实现可重用组件。这里不需要 React、Angular 或 Vue,相反,自定义元素为我们提供一个自定义 HTML 元素中所有结构 (HTML)、样式 (CSS) 和行为 (JavaScript) 的封装。
通过上下两篇实战教程,我们从 0 ~ 1 实现了一个下拉组件。
下拉组件的功能不是很多,API 也不是很多,但是这些都不是重点,重点是通过这两篇实战教程,我希望从这个 Web Components 教程中你可以学到了很多东西。
这篇文章我们将下拉组件运用起来。虽然下拉组件我们的确已经封装完成,但是我们如何将它应用我们的实战项目中了?就像 Element UI、Ant Design 那样。这并不是一个难事。你只需要将它作为一个 npm 包发布出去即可,那这篇文章就是带你将我们的下拉组件再抽象,可作为一个独立的组件包发布,废话不多说,Come on body,let’s go body。
组件发布
要想将我们实战写好的 Web Components 组件用于项目中,我们需要将他们当做一个 npm 包发布为一个可用的包。
发布一个可用的包,我们其实可以将其分为两种情况,如果你发布的包只是简单的包含 JavaScript ,其实我们可以 使用 Babel 发布节点包
;如果你想发布一个用于前端开发的库(例如:Vue、React),你的节点包不经包含 JavaScript,还包含 JSX、SVG、Vue 这些复杂的文件,你可能需要 使用复杂的打包器 Webpack
。是否使用 Babel、Webpack 或任何其他捆绑器(例如 Rollup)来创建开源项目取决于你的要求。
使用 Babel 发布包
首先,我们创建好工程的基础结构,
npm init
初始化工程,使用一下命令安装 babel 的必要包。
npm install @babel/core @babel/node @babel/preset-env @babel/cli --save-dev
在 package.json 中条件基础命令。
"scripts": {
"build": "babel src/index.js --out-dir lib",
"prepare": "npm run build",
"test": "echo "Error: no test specified" && exit 1"
},
npm 构建脚本使用 Babel 将所有文件从src/ 目录编译到 lib/ 目录下。并且由于我们的代码必须在每次发布之前运行,所以这里在 package.json 文件中添加了 prepare
的准备脚本来执行 npm run build。
接着,在运行构建脚本之前,我们可能需要将 Babel 预设添加到 Babel 转译步骤中。所以可以创建一个.babelrc 文件来添加所需的预设。
{
"presets": [
"@babel/preset-env"
]
}
此外,为了不将一些不希望的文件提交,所以将.npmignore文件添加到项目中,以忽略不应包含在已发布节点包中的所有文件/文件夹。例如,不应包含 src/ 文件夹,因为只有 lib/ 文件夹对最终节点包很重要。因此,在您的.npmignore文件中,添加以下行:
src/
最后在我们的 src/index.js 文件中添加一些代码,代码来源 Vue 2 源码中的判断函数。
function isUndef(v) {
return v === undefined || v === null
}
function isDef(v) {
return v !== undefined && v !== null
}
function isTrue(v) {
return v === true
}
function isFalse(v) {
return v === false
}
function isPrimitive(value) {
return (
typeof value === 'string' ||
typeof value === 'number' ||
// $flow-disable-line
typeof value === 'symbol' ||
typeof value === 'boolean'
)
}
function isObject(obj) {
return obj !== null && typeof obj === 'object'
}
var _toString = Object.prototype.toString;
function toRawType(value) {
return _toString.call(value).slice(8, -1)
}
function isPlainObject(obj) {
return _toString.call(obj) === '[object Object]'
}
function isRegExp(v) {
return _toString.call(v) === '[object RegExp]'
}
function isValidArrayIndex(val) {
var n = parseFloat(String(val));
return n >= 0 && Math.floor(n) === n && isFinite(val)
}
function toString(val) {
return val == null ?
'' :
Array.isArray(val) || (isPlainObject(val) && val.toString === _toString) ?
JSON.stringify(val, null, 2) :
String(val)
}
function toNumber(val) {
var n = parseFloat(val);
return isNaN(n) ? val : n
}
export {
isUndef,
isDef,
isTrue,
isFalse,
isPrimitive,
isObject,
toRawType,
isPlainObject,
isRegExp,
isValidArrayIndex,
toString,
toNumber
};
export default toNumber;
npm run build
打包代码,生成打包代码。
最后将我们的打包代码发布出去。发布的流程我这里就不多赘述了。发布完成之后你就可以在你的 npm 上找到你发布的包。
最后就是在项目中引入你发布的依赖包。用于实战了,是不是很简单了,你可以自己动手尝试一下。
// 安装
npm install babel-publish-test@1.0.0
// 引入
import { isDef } from 'babel-publish-test';
使用 webpack 发布包
虽然 Babel 不是 webpack 这类的模块捆绑器,但它具有一些方便的功能,可以从源代码文件夹创建捆绑的 JavaScript 文件。但是,我们一般会遇到更复杂的项目,需要复杂的打包器。
由于我们的组件是 Web Components 组件,我们不单单只有 JavaScript 代码,所以我们使用 webpack 来构建我们的 Web Components 下拉组件。
首先初始化一个基础工程,将我们的项目名、仓库和其他的一些信息进行设置。
npm init
初始化完之后,就利用 webpack 来搭建一个可运行的基础服务。安装 webpack
、webpack-cli
、webpack-dev-server
。这里主要是让我们使用 webpack 来执行任务,而不是使用 Babel 来转换源文件。
npm install webpack webpack-cli webpack-dev-server --save-dev
安装完依赖之后,写两个配置文件 webpack.dev.config.js
和 webpack.prod.config.js
,webpack.dev.config.js
用于开发环境的 webpack 配置,webpack.prod.config.js
用于生产环境的 webpack 配置。
// webpack.dev.config.js
module.exports = {
entry: './src/index.js',
output: {
path: __dirname + '/public',
publicPath: '/',
filename: 'bundle.js'
},
devServer: {
static: './public',
open: true
}
};
基本上,webpack 配置有关任务的输入和输出的信息。我们的 src/index.js文件的入口配置保持不变。但是,输出配置需要的信息不仅仅是输出路径(例如/dist)和文件(例如index.js)。库名称应与package.json中节点包的名称相同。库目标应设置为 umd。
// webpack.prod.config.js
module.exports = {
entry: './src/index.js',
output: {
path: __dirname + '/dist',
filename: 'bundle.js',
library: 'baixiaobai-web-components-dropdown',
libraryTarget: 'umd',
},
devtool: 'source-map',
};
并且,如果你想的项目中还需要用到 bebel, 你可能还需要安装依赖,设置模块规则。例如:
module: {
rules: [
{
test: /.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader'],
},
],
},
但是这也是在你需要的情况下,如果不需要就完全没有必要。
接着往下,新建 src 目录,放我们之前写好的下拉组件代码。这里包含两个文件,一个是 index.js
,一个是button.js
。前者既是入口文件也是下拉组件文件,后者是下拉组件的触发对象。
新建 public 目录,存放开发是的入口 html。
最后在 package.json
中配置构建和打包命令,随带在配置一个 main 入口配置。
"main": "dist/bundle.js",
"scripts": {
"start": "webpack-dev-server --config ./webpack.dev.config.js --mode=development",
"build": "webpack --config ./webpack.prod.config.js --mode=production",
"prepare": "npm run build",
"test": "echo "Error: no test specified" && exit 0"
},
当然还少不了 .gitignore
、.npmignore
的配置。
// .gitignore
npm-debug.log*
yarn-debug.log*
yarn-error.log*
node_modules
public
.npmrc
// .npmignore
public/
src/
到这里我们的基础工程就配置完了,完整目录如下:
我们运行一下我们的项目。看是否正常。
工程的开发和构建都能正常运行。到这里工程就完成了。你也可以将我这里的代码 clone 下来自己操作一下。
git clone git@github.com:LK-Champ/baixiaobai-web-components-dropdown.git
cd baixiaobai-web-components-dropdown
npm install
npm run start
visit http://localhost:8080
工程搭建完成之后,就是将我们这个工程中的下拉组件 baixiaobai-web-components-dropdown
发布出去。
npm run build
打包代码,生成打包代码。
让它能运用于我们的实际项目中。当然这里我发布的具体流程也不多赘述了。
测试代码地址:https://github.com/LK-Champ/baixiaobai-web-components-dropdown
npm 包地址:https://www.npmjs.com/package/baixiaobai-web-components-dropdown
到这里我们的 Web Components 下拉组件就已经发布完成了。
在项目中使用下拉组件
组件发布完成,为了保证我们的组件是可用的,我们启动一个项目来测试一下。
使用 Create React App 创建一个单页 React 应用程序。
npx create-react-app my-app
cd my-app
npm start
接着安装我们的下拉组件。
npm install baixiaobai-web-components-dropdown@1.0.0
安装完成,引入看看什么样?看看是不是和我们实战中的效果一样。
import React from 'react';
import 'baixiaobai-web-components-dropdown';
function App() {
const props = {
label: '下拉菜单组件',
option: 1,
options: [
{ "label": "黄金糕", "value": 1 },
{ "label": "狮子头", "value": 2 },
{ "label": "螺蛳粉", "value": 3 },
{ "label": "双皮奶", "value": 4 },
{ "label": "蚵仔煎", "value": 5 }
]
};
React.useEffect(() => {
document
.querySelector('baixiaobai-web-components-dropdown')
.addEventListener('onOptionChange', (event) => {
console.log(event.detail);
});
}, [])
return (
<div className="App">
<baixiaobai-web-components-dropdown
{...props}
></baixiaobai-web-components-dropdown>
</div>
);
}
export default App;
nice,发现是一样的。这也就宣告了我们的 Web Components 下拉组件成功了。已经能成功的将这个下拉组件用于生产项目中了。
总结
通过之前上下两篇实战,我们从 0 ~ 1 实现了一个下拉组件。本文我们又将我们实战中实现的下拉组件通过 npm 依赖包的方式发布到了 npm 资源库中,将我们的 Web Components 组件能用于生产项目。我们不仅实现了 0~1 的过程,还更近了一步,从 1 ~ 2 ,整个过程都是比较简单了,如果你有兴趣可以自己去实战一下。并且如果你对 Web Components 非常有兴趣,利用之前实战的思想,自己实现一个 Web Componetns 组件库,都并非难事。
最后,我希望从这个 Web Components 教程中你可以学到了很多东西。
如果文中有什么问题或者错误,请在评论区告诉我。
如果你觉得这篇文章对你有帮助,点个赞吧。
暂无评论内容