教你如何为所欲为的开发前端公共组件库,并打包上传到npm上

「本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你挑战!

还在为不知如何开发前端公共组件库而烦恼吗?还在为不知道如何把开发好的公共组件库打包上传到npm上吗?这里我都可以一一教会你

我们将会从两个方向出发,第一种是框架组件,如VuereactAngular…等。第二种则是工具组件,如 JavaScriptJQ…等。废话不多说,直接进入我们的主题。

框架组件

这里以Vue2.x为例
复制代码

第一步:使用 vue init webpack-simple yyl-npm-practice 初始化项目

提示: 不要用 vue init webpack npm-practice 初始化项目,因为我们就开发个组件,不需要那么多配置,配置多了修改起来也麻烦,webpack-simple足够了。

初始完项目,按照提示输入项目信息即可,然后 npm install , npm run dev 让项目跑起来,如下图:

872412-20190413134048730-192549904.png

第二步:修改文件目录

1.在src目录下新建components文件夹,然后在此文件夹下建立Main.vue文件

  Main.vue 名字也可以是其他,我们写的这个组件就是放在该文件里面,之前的App.vue是用于本地开发,测试用的入口文件,也就是用于 npm run dev 的入口文件。

2.在webpack.config.js同级目录(也是该组件的根目录)下新建 index.js文件, index.js是把Main.vue文件暴露出去的出口。

修改完之后的文件目录如下,标红的就是新增的内容:

872412-20190413135247686-1665090067.png

第三步:修改文件内容,配置

1.Main.vue内容如下(注意name):

<template>
  <div class="container">
    <div>{{msg}}</div>
    <div>{{propData}}</div>
  </div>
</template>

<script>
export default {
  name: 'yyl-npm-practice',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  },
  props: {
      propData: {
          type: String,
          default: '我是默认值'
      }
  }
}
</script>

<style lang="scss">
.container{
    text-align: center;
}
</style>
复制代码

2.App.vue内容如下:

<template>
  <div>
    <Main :propData='initData'/>
  </div>
</template>

<script>
import Main from './components/Main'
export default {
    data(){
      return {
        initData: 'hello 这里是陈杨下的年华'
      }
    },
    components:{
      Main
    }
}
</script>

<style>

</style>
复制代码

3.index.js内容如下:

import Main from './src/components/Main'
 
// 这一步判断window.Vue是否存在,因为直接引用vue.min.js, 它会把Vue绑到Window上,我们直接引用打包好的js才能正常跑起来。
if (typeof window !== 'undefined' && window.Vue) {
window.Vue.component('yyl-npm-practice', Main)
}
//这样就可以使用Vue.use进行全局安装了。
Main.install = function(Vue){
Vue.component(Main.name, Main)
}
export default Main
复制代码

—— start 2019-05-06新增

index.js内容改完如下, 因为使用 window.Vue.component(‘yyl-npm-practice’, Main) 的时候 外部引用的时候 有可能会覆盖该组件,导致组件无法正常使用;

使用下面的的定义方式后, 在.vue 环境下 使用方式不变, 在只引用 ys-expression.js 环境下

需在 new Vue() 之前加 window[‘ys-expression’].default.install();

import Main from './src/component/Main'
import _Vue from 'vue'

Main.install = Vue => {
if (!Vue) {
window.Vue = Vue = _Vue
}
Vue.component(Main.name, Main)
}
export default Main;
复制代码

—— end 2019-05-06新增

4.修改package.json

package.json需要修改private字段(private是true的时候不能发布到npm,需设置成false); 并增加main字段, main字段是require方法可以通过这个配置找到入口文件,这输入模块加载规范,具体可以参考 这里, 主要内内容截图如下:

872412-20190413141046072-2009356377.png

修改完package.json如下,标红的就是新增和改变的属性。

872412-20190413140615983-442956056.png

5.修改 webpack.config.js
其实就是修改entry 和output,截图如下:

872412-20190413141834023-1036786115.png

说明:入口会根据开发环境 ,生产环境切换, main.js 是npm run dev 的入口,就是App.vue, 用于调试/测试我们开发的组件; index.js是Main.vue, 就是我们开发的组件,我们打包到生产环境打包就只是单纯的 yyl-npm-practice 组件

6.修改index.html的js引用路径,因为我们修改了output 的 filename,所以引用文件的名字也得变。

872412-20190413144119806-1318062074.png

到此组件就开发完了,打包下看看, npm run build dist下生成了俩文件,如下:

872412-20190413142640156-973748135.png

这个.map文件怎么回事,其实就是这段代码:

872412-20190413142814520-358347593.png

生产环境的时候, 我们就不调试了,也不想要这个.map文件,那就先把这个 devtool删了,然后放在这里,看下图,只要在开发环境的时候才启用这个调试,

872412-20190413143325761-1330974957.png

把dist目录下的俩文件删除,再npm run build 就不会产生.map文件了。

npm run dev 让项目跑起来,我们在App.vue里面调用该组件,并做测试,调试。

第四步: 发布到npm

  1. 去 npm 官网注册个账号 www.npmjs.com/

2.在该组件根目录下的终端(就是 平常输入 npm run dev的地方),运行npm login,会提示输入个人信息,Email是发布成功后,自动给这个邮箱发送一个邮件,通知发布成功,输入完,登录成功。

去自己的npm上点击Packages ,就能看到发布的包

872412-20190413145905774-579833772.png

包的具体信息如下:

872412-20190413154554888-529949089.png

大家最好在readme 里面写上组件的使用方法, 说明等等,方便你我他。

使用方法 :

1.组件内部使用

html: 

  <Main/>

js:

    import Main from 'yyl-npm-practice'

    components: {
      Main
    }

复制代码
  1. main.js 全局安装:
import Main from 'yyl-npm-practice'
Vue.use(Main)
复制代码

然后在其他.vue文件里面,直接使用组件 即可

3.直接引用打包后的 yyl-npm-practice.js

这种方式就不需要webpack这类的构建工具,跟jquery的方式差不多,可以直接页面引用,使用方法示例如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
</head>
<body>
<div id="app">
  <yyl-npm-practice :propData="propData"></yyl-npm-practice>
</div>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="./dist/yyl-npm-practice.js"></script>
<script>
  new Vue({
    el: '#app',
    data: function() {
      return {
        propData: '11111111111111111111'
      }
    },
    methods: {
    }
  })
</script>
</body>
</html>
复制代码
采坑记录:

1. 在webpack.config.js里设置 resolve(比如 设置@做为根目录 ), 开发环境没问题,生产环境就用不了了,所以大家就用平常的相对路径类吧,虽然麻烦了点。

2. 图片生产环境不能用,解决方法可以把图片转成base64, 可以用这个 在线图片转base64,或者把图片放在网上,引用图片的网上资源路径。

3. 字体图标在生产环境也用不了,如果用到了字体图标,就别把字体图标的资源打包进去了,引用该组件的时候,需要再引用字体图标的资源。
复制代码

start ====> 2019-04-17更新

后来发现其实图片和字体图标也可一起打包到js里面,需要用到 url-loader 把limit参数设置大点就行,这样就可以把图片,字体图标也都打包到js里面了,这样使用的时候,就不用单独引用这些静态资源了, 代码如下:

{
    test: /\.(png|jpg|gif|svg)$/,
    loader: 'url-loader',
    options: {
      name: '[name].[ext]?[hash]',
      limit: 99999
    }
    },
    { 
    test: /\.(svg|ttf|eot|woff|woff2)$/, 
    loader: 'url-loader', 
    options:{ 
     name:'[name].[ext]',
        limit: 9999999
    } 
}
复制代码

第二种工具库

这里以JavaScript为例子。 开发Js的工具库不需要像框架一样那么复杂,不需要webpack打包机制,我们使用rollup.js打包工具即可

第一步,安装rollup.js打包工具

rollup.js按照官网的原话说:

Rollup 是一个 JavaScript 模块打包器,可以将小块代码编译成大块复杂的代码,例如 library 或应用程序。

Rollup 对代码模块使用新的标准化格式,这些标准都包含在 JavaScript 的 ES6 版本中,而不是以前的特殊解决方案,如 CommonJS 和 AMD。ES6 模块可以使你自由、无缝地使用你最喜爱的 library 中那些最有用独立函数,而你的项目不必携带其他未使用的代码。ES6 模块最终还是要由浏览器原生实现,但当前 Rollup 可以使你提前体验。

1.全局安装 rollup

npm i rollup -g
复制代码

2.新建项目,初始项目

mkdir rollup-demo ## 新建项目文件夹
cd rollup-demo    ## 进入项目根目录
npm init          ## 初始化项目
复制代码

第二步,编写插件源码bundle.js

1.创建 src/main.js 编写源码

cd rollup-demo ## 进入项目根目录
mkdir src      ## 创建 src 目录
cd src
touch main.js  ## 在 src 目录下创建 main.js
复制代码

2.main.js 文件内容

var answer = '100';
export default function () {
  console.log(`the answer is ${answer}。`);
}
复制代码

第三步,工具库的相关配置

1.rollup 配置文件

项目根目录下新建 rollup.config.js

export default {
  input: 'src/main.js',  // 入口文件
  output: {  // 输出 options
    file: 'bundle.js',  // 输出文件名
    format: 'cjs'       // 输出格式
  }
}
复制代码

2.修改 package.json 的 scripts

"scripts": {
   "dev": "rollup -c"  // 打包命令
}
复制代码

运行 npm run dev 打包编译

1567373-42264fb97c88b0e1.webp

生成的bundle.js 文件内容:

'use strict';

var answer = '100';
function main () {
  console.log("the answer is ".concat(answer, "\u3002"));
}

module.exports = main;
复制代码

3.使用插件编译 babel

3.1 安装 rollup-plugin-babel

npm i -D rollup-plugin-babel
复制代码

编辑 rollup.config.js,添加插件配置

import babel from 'rollup-plugin-babel';

export default {
  input: 'src/main.js',
  output: {
    file: 'bundle.js',
    format: 'cjs'
  },
  plugins: [ // 增加 plugins
    babel({
      exclude: 'node_modules/**' // 不对node_modules进行编译
    })
  ]
}
复制代码

3.2 安装 babel 的相关依赖

npm i -D @babel/core @babel/preset-env
复制代码

在 src 目录下添加 .babelrc 配置文件 (项目根目录下也是可以的,区别在于 src 目录下的 .babelrc 只会影响 src 目录下的文件)

{
  "presets": [
    ["@babel/env", {"modules": false}]
  ]
}
复制代码

3.3 将 main.js 更改为es6语法

const answer = '100';
export default () => {
  console.log(`the answer is ${answer}。`);
}
复制代码

重新打包

npm run dev

当前 bundle.js 的内容

'use strict';

var answer = '100';
var main = (function () {
  console.log("the answer is ".concat(answer, "\u3002"));
});

module.exports = main;
复制代码
  1. 使用 npm packages 依赖

rollup 不知道如何处理 node_modules 中的依赖,需要通过插件 rollup-plugin-node-resolve 告诉 rollup 如何查找外部模块。

npm i -D rollup-plugin-node-resolve
复制代码

编辑 rollup.config.js

import resolve from 'rollup-plugin-node-resolve';
import babel from 'rollup-plugin-babel';

export default {
  input: 'src/main.js',
  output: {
    file: 'bundle.js',
    format: 'cjs'
  },
  plugins: [
    resolve(),
    babel({
      exclude: 'node_modules/**'
    })
  ]
}
复制代码

现在就可以去代码中引用 node_modules 中的依赖了,以 the-answer 为例:

npm i the-answer
复制代码

在 main.js 中引用 the-answer

import answer from 'the-answer';

export default () => {
  console.log(`the answer is ${answer}。`);
}
复制代码

打包编译后的结果:

'use strict';

var index = 42;

var main = (function () {
  console.log("the answer is ".concat(index, "\u3002"));
});

module.exports = main;

复制代码

打包发布npm

这里的流程我就不重复说,跟上面的Vue组件库打包上传的流程是一样的(其实就是偷懒…,大家懂了就好,见谅见谅)

补充

今天的技术就介绍到这里了,大家有什么建议的可以下面评论,我会第一时间回,或者有什么问题我们都可以讨论,谢谢大家,创作不易,请多多支持点赞、分享

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享