精华内容
下载资源
问答
  • 封装vue组件库的两种方法和形式: 一:是建立一个webpack-simple 项目 二:是在通过vue-cli脚手架建立webpack vue项目,这种项目有点冗余,可是我们对这种项目最熟悉 下面分别介绍两种用法: 一: 1.首先先建立...

    封装vue组件库的两种方法和形式:

    一:是建立一个webpack-simple 项目

    二:是在通过vue-cli脚手架建立webpack vue项目,这种项目有点冗余,可是我们对这种项目最熟悉

    下面分别介绍两种用法:

    一:

    1.首先先建立一个vue项目:

    通过vue init webpack-simple,新建项目目录如下:

    箭头指的是在项目打包后产生的文件(打包命令npm run build )

    2.在src下新建一个目录用来存放组件源码:

    然后写封装的组件,比如radios/radio.vue

    3.组件封装完后新建index.js文件,作为我们组件库的出入口,index.js内容如下:

    展开全文
  • 而且各自基于公共又搞了一套自己的库,为了收紧口子跟后期的维护扩展,决定把公共库打包发布到npm私服,然后install到各自业务线,确保各业务线一致,这是背景 打包 在这之前有使用rollup打包的经验,这里也计划用...

    背景

    公司的前端组件库经过前端好几位大佬搞了个基于React、Ant design二次扩展的库,之前设想是每个业务模块基于公共的组件库维护各自的业务组件库,经过几个周期之后,发现已经不可控了,每个业务模块的Ant design版本不一样,而且各自基于公共又搞了一套自己的库,为了收紧口子跟后期的维护扩展,决定把公共库打包发布到npm私服,然后install到各自业务线,确保各业务线一致,这是背景

    打包

    在这之前有使用rollup打包的经验,这里也计划用rollup来实现,这过程中碰到了不少问题,查阅相关资料发现国内基于Rollup打包React的比较少,所以基于这次经验想整理下,以便后续查阅,过程中遇到的相关问题如下:

    • 由于工程默认导出文件夹下的index.js文件,打包报错引入rollup-plugin-commonjs插件
    • React组件的"<"解析报错,引入@babel/preset-react解决
    • rollup.config.js plugins顺序不正确,先babel()再commjs(),不然commjs()打包报第2个错误
    • class组件中的属性报错,引入@babel/plugin-proposal-class-properties解决
    • class组件中的修饰符@打包报错,引入@babel/plugin-proposal-decorators解决,.babelrc 顺序必须在class-properties前
    • 代码中使用的新特性解析报错,引入@babel/preset-env解决
    • 使用rollup-plugin-less/rollup-plugin-less-modules打包出来引入的CSS文件不对,替换成rollup-plugin-postcss/rollup-plugin-less

    启动

    • 运行打包文件报错,引入babel @babel/plugin-transform-runtime解决
    • 再运行,这个报错是因为 async/await 导致的,这个问题找了很久,最终在issues找到解决方案

    第一个问题,回退到这个版本"@babel/plugin-transform-runtime": “7.1.0”/"@babel/runtime": "7.1.2"解决;
    后面三个问题是ESLINT检查导致的,关闭ESLINT解决

    • 之前整个库之间有相互的引用,导致打包之后生成的index.js里面还有import库下的引用与绝对路径的引用,导致运行时无法找到引用的文件报错,rollup认为yss-biz是一个依赖,但是运行时实际并不存在,最后引入rollup-plugin-includepaths把yss-biz别名转成相对路径
    • uglif插件压缩报错,替换成rollup-plugin-terser解决

    最后打包成功

    • Unused external imports 这个问题是因为import了uglify但是没用,忽略
    • Circular dependencies 因为历史原因,库中有使用yss-biz这个alias,后面通过rollup-plugin-includepaths重新定义这个别名的指向,最终出现循环引用,忽略
    • this has been rewritten to undefined 这是因为库中写的代码不正确用了箭头函数然后还绑定了this忽略
    • Unused external imports 这个是因为导入的内容没有使用,忽略

    配置

    rollup.config.js

    import commonjs from "rollup-plugin-commonjs";
    import babel from "rollup-plugin-babel";
    import postcss from "rollup-plugin-postcss";
    import ascii from "rollup-plugin-ascii";
    import resolve from "@rollup/plugin-node-resolve";
    import includePaths from "rollup-plugin-includepaths";
    import { terser } from "rollup-plugin-terser";
    
    const externalAry = [
      "antd",
      "antd/es/locale/zh_CN",
      "antd/dist/antd.css",
      "moment",
      "moment/locale/zh-cn",
      "echarts",
      "prop-types",
      "snowflake-id",
      "win-trade-base",
      "@lugia/lugiax",
      "@ant-design/icons",
      "react",
      "react-transition-group",
      "react-dnd",
      "react-dnd-html5-backend",
      "react-loadable",
      "react-resizable",
    ];
    
    export default {
      input: "yss-biz-base/index.js",
      output: {
        file: "dist/index.js",
        format: "esm",
        sourcemap: true,
      },
      plugins: [
        resolve(),
        includePaths({
          include: { "yss-biz": "./yss-biz-base/index.js" },
        }),
        babel({ exclude: "**/node_modules/**", runtimeHelpers: true }),
        commonjs(),
        ascii(),
        postcss({
          // Extract CSS to the same location where JS file is generated but with .css extension.
          extract: true,
          // Use named exports alongside default export.
          namedExports: true,
          // Minimize CSS, boolean or options for cssnano.
          minimize: true,
          // Enable sourceMap.
          sourceMap: true,
          // This plugin will process files ending with these extensions and the extensions supported by custom loaders.
          extensions: [".less", ".css"],
        }),
        terser(),
      ],
      //不能使用正则匹配,有定制化组件也是以echarts命名
      external: externalAry,
    };
    

    package.json

      "dependencies": {
        "@babel/core": "^7.10.0",
        "@babel/plugin-proposal-class-properties": "^7.8.3",
        "@babel/plugin-proposal-decorators": "^7.10.0",
        "@babel/plugin-syntax-jsx": "^7.8.3",
        "@babel/plugin-transform-react-jsx": "^7.9.4",
        "@babel/plugin-transform-runtime": "7.1.0",
        "@babel/preset-env": "^7.10.0",
        "@babel/preset-react": "^7.10.0",
        "@babel/runtime": "7.1.2",
        "@rollup/plugin-node-resolve": "^8.0.0",
        "rollup": "^2.10.9",
        "rollup-plugin-ascii": "^0.0.3",
        "rollup-plugin-babel": "^4.4.0",
        "rollup-plugin-commonjs": "^10.1.0",
        "rollup-plugin-includepaths": "^0.2.3",
        "rollup-plugin-less": "^1.1.2",
        "rollup-plugin-postcss": "^3.1.1",
        "rollup-plugin-terser": "^6.1.0"
      },
      "devDependencies": {
        "colors": "^1.4.0",
        "inquirer": "^7.1.0"
      }
    

    .babelrc

    {
      "presets": ["@babel/preset-env", "@babel/preset-react"],
      "plugins": [
        "@babel/plugin-syntax-jsx",
        ["@babel/plugin-proposal-decorators", { "legacy": true }],
        "@babel/plugin-proposal-class-properties",
        "@babel/plugin-transform-react-jsx",
        "@babel/plugin-transform-runtime"
      ]
    }
    

    发布

    发布到npm私服部分网站资料比较多,按照步骤来基本就没什么问题了

    资料

    https://www.bilibili.com/video/av89385215

    https://github.com/rollup/rollup-plugin-babel/issues/209

    第一次记录写文章,文笔有限,多多包涵,ヾ(´ー`)ノ゛谢谢♪

    展开全文
  • 本文将会介绍如何将自己写的组件库打包成第三方库,发布到 npm 上,同时支持在原生 js / React/ Vue 下使用。Webpack4 的升级指南可以参考下 Webpack4.0 升级配置,本文不做赘述。 使用 Webpack4.0 打包 // src/...

    本文首发于 dawei.lv

    本文将会介绍如何将自己写的组件库打包成第三方库,发布到 npm 上,同时支持在原生 js / React/ Vue 下使用。Webpack4 的升级指南可以参考下 Webpack4.0 升级配置,本文不做赘述。

    使用 Webpack4.0 打包

    // src/index.js
    exports default function Tree() {
        console.log('Hello Tree')
    }
    复制代码

    假设我们有上面的 index.js 文件,我们想要把打它打包成一个 tree.js 和一个 tree.min.js 包,并且我希望我既可以通过 <script src="../dist/tree.js"></script> 直接 new Tree() ,又可以通过 import Tree from 'tree'let Tree = require('tree') 引入,怎么做呢?这就要使用 Webpack 来处理了。

    Webpack 不仅可以打包 React / Vue 相关的项目工程,也可以单独打包 js 组件。先来看下入口与出口的配置:

    module.exports = {
      //...
      mode: "none",
      entry: {
        tree: "./src/index.js",
        "tree.min": "./src/index.js"
      },
      output: {
        filename: "[name].js",
        libraryExport: "default",
        library: "Tree",
        libraryTarget: "umd"
      }
      //...
    };
    复制代码

    mode

    Webpack4.0 会在默认情况下开启 mode=production,这会无差别的压缩我们的 tree.jstree.min.js,这不是我们想要的,禁用它。

    entry

    entry 里面我们配置两个入口 tree"tree.min",让 webpack 可以打包出两个文件,我们可以针对两个入口做不同的处理。

    output

    outputfilename 表示打包出来文件名叫什么。libraryExport=default 表示打包出来的组件直接对外暴露 default 属性,否则我们调用的时候需要 new Tree.default(),这不是我们希望的调用方式。library=Tree 表示对外暴露的组件叫什么,如果这个地方修改成了 library=Bar,那我们调用的时候就是 new Bar()libraryTarget=umd 表示采用 UMD (Universal Module Definition) 的方式打包 js,同时支持在 CommonJS、AMD 和全局变量使用。

    optimization

    怎么对 tree.min.js 压缩,但不对 tree.js 压缩呢?请看下面的配置部分:

    // ...
      optimization: {
            minimize: true,
            minimizer: [
                new UglifyJSPlugin({
                    include: /\.min\.js$/,
                }),
            ],
        },
    // ...
    复制代码

    通过 include 设置只压缩 min.js 结尾的文件,是不是很简单。这样我们就得到了 dist/tree.min.jsdist/tree.js 两个文件。下面我们开始发布代码到 npm。

    发布组件库到 npm 上

    发布之前

    发布之前,还有件事需要做,在项目根目录新建 index.js,添加内容

    if (process.env.NODE_ENV === "production") {
      module.exports = require("./dist/tree.min.js");
    } else {
      module.exports = require("./dist/tree.js");
    }
    复制代码

    修改 package.jsonmainindex.js,指定我们通过 import / require 的时候入口文件位置。

    注册 npm

    想要发布代码到 npm 上,需要先注册一个账号,你可以直接打开官网注册,这里我们选择更 cooooool 的方式注册。

    npm adduser
    复制代码

    依次输入 Username、Password、Email 完成注册。

    登录 npm

    注册好账号之后需要在 Terminal 上登录 npm,在 Terminal 中直接注册的同学就不需用登录了。

    npm login
    复制代码

    输入 Username、Password、Email 完成登录。

    发布到 npm

    npm publish
    复制代码

    发布的包名就是你的 package.jsonnameversion。有冲突的话需要换一个哦。

    最后

    本文其实是笔者近期在开源的一个树形选择控件 @widgetjs/tree 摸索出来的打包经验总结。为了简化配置,突出重点,省略了一些生产环境需要添加的较为繁琐的细节,正式的生产模式配置可以在 github 上找到,也欢迎使用,多多提出意见。

    展开全文
  • ① 使用Vue-cli3搭建项目 vue create demo vue-cli3官方文档 注:cli3 提供一个可选的 vue.config.js 配置文件。如果这个文件存在则他会被自动加载,所有的对项目和webpack的配置,都在这个文件中。...

    ① 使用Vue-cli3搭建项目

    vue create demo
    

    vue-cli3官方文档

    注:cli3 提供一个可选的 vue.config.js 配置文件。如果这个文件存在则他会被自动加载,所有的对项目和webpack的配置,都在这个文件中。
    新建vue.config.js配置文件:下面是一些通用配置

    const path = require('path')
    
    module.exports = {  
      // 部署应用包时的基本 URL,用法和 webpack 本身的 output.publicPath 一致
      publicPath: './',  
      // 输出文件目录
      outputDir: 'dist',  
      // eslint-loader 是否在保存的时候检查
      lintOnSave: true,  
      // 是否使用包含运行时编译器的 Vue 构建版本
      runtimeCompiler: false,  
      // 生产环境是否生成 sourceMap 文件
      productionSourceMap: false,  
      // 生成的 HTML 中的 <link rel="stylesheet"> 和 <script> 标签上启用 Subresource Integrity (SRI)
      integrity: false,  
      // webpack相关配置
      chainWebpack: (config) => {
        config.resolve.alias
          .set('vue$', 'vue/dist/vue.esm.js')
          .set('@', path.resolve(__dirname, './src'))
      },
      configureWebpack: (config) => {    
      if (process.env.NODE_ENV === 'production') {      
          // 生产环境
          config.mode = 'production'
        } else {      
          // 开发环境
          config.mode = 'development'
        }
      },  
      // css相关配置
      css: {    
        // 是否分离css(插件ExtractTextPlugin)
        extract: true,    
        // 是否开启 CSS source maps
        sourceMap: false,   
        // css预设器配置项
        loaderOptions: {},    
        // 是否启用 CSS modules for all css / pre-processor files.
        modules: false
      },  
      // 是否使用 thread-loader
      parallel: require('os').cpus().length > 1, 
      // PWA 插件相关配置
      pwa: {}, 
      // webpack-dev-server 相关配置
      devServer: {
        open: true,
        host: 'localhost',
        port: 8080,
        hot: true,
        https: false,
        hotOnly: false,   
        // http 代理配置
        proxy: {      
          '/api': {
            target: 'http://127.0.0.1:3000/api',
            changeOrigin: true,
            pathRewrite: {          
                '^/api': ''
            }
          }
        },
        before: (app) => {}
      }, 
      // 第三方插件配置
      pluginOptions: {
    
      }
    }
    

    ②在components文件下新建一个组件

    <template>
      <div class="a">
        <h5 class="b" :data="sdata" :style="{color: sdata.color, fontSize : sdata.fontSize + 'px'}">{{ sdata.desc }}</h5>
      </div>
    </template>
    
    <script>
    export default {
      name: "Comone",
      props: {
        sdata: Object
      }
    };
    </script>
    
    <style scoped>
    .a {
      padding: 10px;
    }
    .b{
      color: coral;
      background-color: lightgreen;
    }
    </style>
    
    

    标题③在components文件下新建index.js文件,对外提供对组件的引用。

    // 导入组件,组件必须声明 name
    import Comone from './one/Comone'
    import Comtwo from './two/Comtwo'
    // 存储组件列表
    const components = [
      Comone,
      Comtwo
    ]
    // 定义 install 方法,接收 Vue 作为参数。如果使用 use 注册插件,则所有的组件都将被注册
    const install = function (Vue) {
     // 判断是否安装
     if (install.installed) return
     // 遍历注册全局组件
     components.map(component => Vue.component(component.name, component))
    }
    // 判断是否是直接引入文件
    if (typeof window !== 'undefined' && window.Vue) {
     install(window.Vue)
    }
    export default {
     // 导出的对象必须具有 install,才能被 Vue.use() 方法安装
     install,
     // 以下是具体的组件列表
     Comone,
     Comtwo
    }
    

    ④可以现在当前的main.js里试用是否生效

    import Sortt from './components/index'
    
    Vue.use(Comone )
    Vue.config.productionTip = false
    
    new Vue({
      render: h => h(App),
    }).$mount('#app')
    

    ⑤上面全局引入了,这边新建一个xxx.vue文件使用测试

    <template>
        <Comone :sdata="sdata" />
    </template>
    
    <script>
    export default {
      data () {
            return {
              sdata: {
    	        desc: 'xxxxx2345xxxx',
    	        color: 'green'
    	      },
           }
       }
    }
    </script>
    

    ⑥配置 package.json 文件中发布到 npm 的字段

    1. name: 包名,该名字是唯一的。可在 npm 官网搜索名字,如果存在则需换个名字。
    2. version: 版本号,每次发布至 npm 需要修改版本号,不能和历史版本号相同。
    3. description: 描述。
    4. main: 入口文件,该字段需指向我们最终编译后的包文件。
    5. keyword:关键字,以空格分离希望用户最终搜索的词。
    6. author:作者
    7. private:是否私有,需要修改为 false 才能发布到 npm,变成开源组件包。内网私有包要设置为true
    8. license: 开源协议

    示例:这里一定要配置main入口文件,否则无法获取到组件,报错为组件未定义,main.js的入口文件为下面的打包后压缩文件路径

    {
      "name": "coms",
      "version": "0.1.0",
      "description": "一个demo组件",
      "main": "lib/anyname.umd.min.js",
      "keyword": "coms comone ...",
      "private": false
     }
    

    配置.gitignore文件,设置发布忽略文件

    .DS_Store
    node_modules
    /dist
    # 忽略目录
    
    examples/
    packages/
    public/
    
    # 忽略指定文件
    vue.config.js
    babel.config.js
    
    # 编辑器目录和文件
    .idea
    .vscode
    *.suo
    *.ntvs*
    *.njsproj
    *.sln
    *.sw?
    *.map
    

    ⑦打包组件库,在page.json里配置新增一个lib打包命令

    1. –target: 构建目标,默认为应用模式。这里修改为 lib 启用库模式。
    2. –dest : 输出目录,默认 dist。这里我们改成 lib
    3. [entry]: 最后一个参数为入口文件,默认为 src/App.vue。这里我们指定编译 components/ 组件库目录。
    "scripts": {
        // ...
        "lib": "vue-cli-service build --target lib --name anyname --dest lib src/components/index.js"
    }
    

    执行打包命令

     $ npm run lib
    

    ⑧登录npm,并注册账号,发布开源组件包

    首先需要到 npm 上注册一个账号,并验证邮箱认证,注册过程略。

    如果配置了淘宝镜像,先设置回npm镜像:

    $ npm config set registry http://registry.npmjs.org 
    

    然后在终端执行登录命令,输入用户名、密码、邮箱即可登录。

    $ npm login
    

    执行发布命令,发布组件到 npm

    $ npm publish
    

    发布成功后稍等几分钟,即可在 npm 官网搜索到。一般更新的需要10分钟

    这时已经可以下载组件包

    $ npm install --save coms
    

    使用组件包和第④、⑤步骤一样进行使用,主要的是main.js需要引入样式

    import 'anyname.css'
    

    ⑨创建npm非开源内网组件包的方式

    通常通过 npm 来安装和使用开源的模块。但是,通常我们有些私有的模块,不想通过npm发布,但是又想在一些项目中共享使用,而且我们不想将公共模块是复制到各个项目中来使用。
    现在探讨的是另一种方式——利用现有的git,既不用搭建私有的npm私有仓库(npm private repository),又能满足上面的需求,它做为一个快速解决方案, 后期是可以慢慢过渡升级到使用完整 npm 私有仓库的解决方案的.

    新建 npm 私有模块

    下面以一个实例来说明如何在 GitLab 中新建一个 npm 私有模块, 假设我们要新建的私有模块名为: wave-test

    GitLab 上新建一个 project, 名字为: any-name
    对于公共模块, 最好是放在同一个 group 下, 例如放在 anygroup 这个 group 下. 那么以后所有公共模块的 git 地址就可以统一为:

    http://git.your-inc.com/{group}/{project}.git
    

    将项目 clone 下来

    git clone http://git.your-inc.com/anygroup/any-name.git
    添加 package.json 配置, 注意限定 @scope

     npm init --scope=anygroup
    

    然后提交 push 上去

    到这里私有模块就已经发布好了, 如果有项目要使用, 就配置下项目的 dependencies 即可.

    使用私有模块

    添加私有模块的依赖
    在项目的 package.json 中添加依赖, 例如: 依赖 @anygroup/any-name 这个私有模块

     "@anygroup/any-name": "git+http://git.your-inc.com/anygroup/any-name.git"
    

    如果想固定依赖某个分支,可以加上分支的名字,比如分支branch1,

     "@anygroup/any-name": "git+http://git.your-inc.com/anygroup/any-name.git#branch1"
    

    安装私有模块

    跟安装开源的模块一样, 使用 npm install 安装依赖即可. 私有模块会安装在 @scope 的子文件夹中, 例如:
    node_modules/@anygroup/any-name

    代码中使用私有模块

    跟使用开源的模块一样, 我们只要写对应的包名即可. 私有模块的包名只是带有 @scope 而已.

    var Comone = require('@anygroup/any-name');
    // 另外一种引用方式
    import Comone from '@anygroup/any-name'
    

    更新私有模块

    如果私有模块的版本更新了, 我们使用 npm update 是无法更新私有模块的, 只能通过

    npm install @anygroup/any-name
    

    这样的方式来重新安装一次私有模块, 才能获取到最新版本的私有模块.

    私有模块的规范

    package.json#name 必须限定 @scope
    @scope 一般为 GitLab group 的名字, 例如 @companyfe, 那么 name 为: @anygroup/any-name

    package.json#private 设置为 true

    防止你一不小心将私有模块发布上去

    配置打包文件,否则依赖包文件太大

    示例依赖包只留打包文件为lib

    "files": [
        "lib"
      ],
    
    {
      "name": "@anygroup/any-name",
      "version": "0.0.1",
      "description": "xx yy",
      "main": "lib/anyname.umd.min.js",
      "private": "true",
      "repository": {
        "type": "git",
        "url": "http://git.your-inc.com/wavesnow/wave-test.git"
      },
      "keywords": [
        "wave",
        "git",
        "tool",
        "javescript"
      ],
      "author": "wavesnow",
      "license": "MIT"
    }
    

    转载自原文简书地址。[^1]

    展开全文
  • 对Vue组件开发有一定了解,对UI组件库的实现比较感兴趣,想要理解其开发原理,这篇文章或许可以帮助你实现并发布自己的第一个自定义插件。 Demo地址 建议将demo拉取至本地,结合代码更容易理解: git地址:...
  • 封装vue组件库,发布npm封装vue组件库组件开发组件库打包发布npm 封装vue组件库 组件库的开发和平时项目中组件的开发过程是一样的,不同的是组件库作为一个插件使用,使用Vue.use()注册插件。 Vue.use方法可以接收一...
  • webpack除了打包应用,也可以用来打包js库和一些自定义组件库。 单纯只是打包js库和组件库的话 使用rollup打包也是一个不错的选择。 我们来实现一个简单的打包例子,这个例子需要满足以下几点功能: 需要支持打包...
  • 在上篇《重新设计 React 组件库》中我们从宏观层面一起探讨了结构自由且数据解耦的 React 组件库应当如何设计,在本文中让我们从具体实践的角度来看如何将这样的设计落地。组件分类在传统的组件库设计中,组件分类...
  • #第一步,修改build中utils.js  添加一句话: #第二步,修改build中webpack.prod.conf.js  将extract属性值修改为false   #第三步,修改config中的index.js ...
  • 打包方式和打包项目时...(3)打包发布 "script":{ "build":"webpack" "prepublish":"webpack" } 添加prepublish钩子,表示执行npm publish的时候会执行"build"命令和该命令 先npm login登录npm账号 ...
  • 这块自己也研究了一下,如何vue组件项目中样式单独打包出一个css文件。 实现方式 主要是使用 extract-text-webpack-plugin 这个插件实现,但是如果你是webpack4以上版本,只能考虑使用 mini-css-extract-plugin 这...
  • 目前主流的前端框架vue和react都采用rollup来打包,为了探索rollup的奥妙,接下来就让我们一步步来探索,并基于rollup搭建一个库打包脚手架,来发布自己的库和组件。前言写rollup的文章是因为笔者最近要规范前端开发...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 66,137
精华内容 26,454
关键字:

组件库打包发布