将 Web Components 组件打包发布


theme: juejin
highlight: tomorrow-night-bright

本文为稀土掘金技术社区首发签约文章,14天内禁止转载,14天后未获授权禁止转载,侵权必究!

近年来,Web Components,也称为自定义元素,已经成为多个浏览器的标准 API,它允许开发人员仅使用 HTML、CSS 、JavaScript 来实现可重用组件。这里不需要 React、Angular 或 Vue,相反,自定义元素为我们提供一个自定义 HTML 元素中所有结构 (HTML)、样式 (CSS) 和行为 (JavaScript) 的封装。

通过上下两篇实战教程,我们从 0 ~ 1 实现了一个下拉组件。

Web Components 入门实战(上篇)

Web Components 入门实战(下篇)

下拉组件的功能不是很多,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 上找到你发布的包。

测试代码地址:https://github.com/LK-Champ/babel-publish-test

npm 包地址:https://www.npmjs.com/package/babel-publish-test

最后就是在项目中引入你发布的依赖包。用于实战了,是不是很简单了,你可以自己动手尝试一下。

// 安装
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 来搭建一个可运行的基础服务。安装 webpackwebpack-cliwebpack-dev-server。这里主要是让我们使用 webpack 来执行任务,而不是使用 Babel 来转换源文件。

npm install webpack webpack-cli webpack-dev-server --save-dev

安装完依赖之后,写两个配置文件 webpack.dev.config.jswebpack.prod.config.jswebpack.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 教程中你可以学到了很多东西。

如果文中有什么问题或者错误,请在评论区告诉我。

如果你觉得这篇文章对你有帮助,点个赞吧。

© 版权声明
THE END
喜欢就支持一下吧
点赞10 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容