Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

通过npm发布的第一个React组件的实践过程 #32

Open
lulujianglab opened this issue Nov 12, 2018 · 0 comments
Open

通过npm发布的第一个React组件的实践过程 #32

lulujianglab opened this issue Nov 12, 2018 · 0 comments

Comments

@lulujianglab
Copy link
Owner

lulujianglab commented Nov 12, 2018

前言

从开始接触react也有差不多四个月时间了,用的频繁了之后,也越发的“默契”。最近在项目中要开发一些定制化组件,写了些组件想要集中的管理,就打算把组件放在npm上,在网上查找资料学习了下,下面就是通过npm发布自己的第一个React组件的实现过程

注册

npm的注册就跟我们注册微博等其他社交账号一样,基本都是输入邮箱、用户名等等信息,十分简单也不耗时

注册网址:https://www.npmjs.com

新建项目

在github上新建一个项目(这里不做过多赘述,相信使用过github的盆友应该会很熟悉),然后git clone下来之后进入到项目目录,执行npm init,按提示输入信息,主要有

  • name:发布的名称
  • version:版本号
  • entry:入口文件

刚开始没填好没关系,后期也可以修改

具体封装实现

我在这个项目里面封装了一个react-hover-menu的组件

这是完成后的项目树:

image

配置package.json

npm相关信息

"name": "react-hover-menu",
"version": "1.0.3",
"description": "react hover or click menu component",
"main": "dist/bundle.js",
"files": [
  "dist"
],
"scripts": {
  "test": "echo \"Error: no test specified\" && exit 1",
  "build": "webpack"
},
  • main: 这里是我们组件的入口文件。开发者在 import 我们的组件的时候会引入这里 export 的内容

  • files: 申明将要发布到 npm 的文件。如果省略掉这一项,所有文件包括源代码会被一起上传到 npm

  • scripts: 加入一个 build 指令来运行 webpack,此时运行的 webpack 是这个当前文件夹内安装的 webpack 而不是 global 的 webpack

依赖

"dependencies": {
  "antd": "^3.10.5",
  "prop-types": "^15.6.0",
  "react": "^16.2.0",
  "react-dom": "^16.6.1"
},
"devDependencies": {
  "babel-core": "^6.26.3",
  "babel-loader": "^7.1.2",
  "babel-plugin-import": "^1.11.0",
  "babel-preset-env": "^1.6.1",
  "babel-preset-react": "^6.24.1",
  "css-loader": "^0.28.11",
  "less": "^3.8.1",
  "less-loader": "^4.1.0",
  "postcss-loader": "^3.0.0",
  "react-hot-loader": "^4.3.12",
  "react-scripts": "^1.1.0",
  "style-loader": "^0.19.1",
  "webpack": "^3.10.0",
  "webpack-node-externals": "^1.6.0"
}

这些依赖是我这个组件需要用到的,具体依赖得根据具体项目需要添加

配置webpack(webpack.config.js)

  • 通过babel准换JSX和ES6的代码

  • 通过css-loader, sytle-loader 引入 css 到打包文件

  • 通过exclude:/src/, css-loader对antd的样式做处理

  • 通过style-loader,css-loader,postcss-loader,less-loader对less样式做处理

  • webpack-node-externals 可以避免把 node_modules 里面的依赖包引入打包文件

  • libraryTarget: "commonjs2" 使测试项目可以找到我们打包后的组件

const path = require('path')
const nodeExternals = require('webpack-node-externals')

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
    libraryTarget: 'commonjs2'
  },
  module: {
    rules: [
      {// 通过babel准换JSX和ES6的代码
        test: /(\.jsx|\.js)$/,
        loader: 'babel-loader',
        exclude: /node_modules/,
        query:
        {
          presets:["env", "react"],
          plugins: [
            [  "import",{libraryName: "antd", style: "css"}] // antd按需加载
          ]
        }
      },
      {// CSS处理
        test: /\.css$/,
        loader: "style-loader!css-loader?modules",
        exclude: /node_modules/,
      },
      {// antd样式处理
        test:/\.css$/,
        exclude:/src/,
        use:[
            { loader: "style-loader",},
            {
                loader: "css-loader",
                options:{
                    importLoaders:1
                }
            }
        ]
      },
      {// less样式处理
        test: /\.less$/,
        use: 
        [
          "style-loader", 
          {
            loader: 'css-loader', 
            options: {
              sourceMap: 1,
              modules:true
            }
          }, 
          {
            loader: "postcss-loader",
            options: {           // 如果没有options这个选项将会报错 No PostCSS Config found
              plugins: (loader) => [
                  require('autoprefixer')(), //CSS浏览器兼容
              ]
            }
          },
          {
            loader: "less-loader",
            options: {
              modifyVars: {
                'primary-color': '#1DA57A',
                'link-color': '#1DA57A',
                'border-radius-base': '2px',
              },
              javascriptEnabled: true,
            }
          }
        ]
      },
    ]
  },
  externals: [nodeExternals()]
}

配置babel(.babelrc)

  • transpile JSX and ES6 code
{
  "presets": ["react","env"],
  "plugins": ["react-hot-loader/babel",["import", { "libraryName": "antd", "libraryDirectory": "lib", "style": "css" }]],
  "env": {
    "production":{
      "preset":["react-optimize"]
    }
  }
}

测试

完成上述步骤后我们就可以在src文件夹里面完成自己的组件,这个时候就可以打包并link让测试项目引入这个打包后的组件进行测试

npm run build

npm link (可能会提示需要管理员权限)

cd [test project folder]

npm link react-hover-menu

创建测试项目

在本地做一个测试项目按上述步骤引入组件就可以看到成果了

使用create-react-app 创建一个 react 项目,并 link 我们刚才完成的组件:

create-react-app demo-menu

cd demo-menu

npm link react-hover-menu

link之后我们就可以直接在页面中引入组件

import HoverMenu from 'react-hover-menu'

发布到NPM

首先先登录npm

npm login

然后发布组件到npm

npm publish

取消发布

npm unpublish

更改版本

更改 package.json 里面的版本号并重新发布

出现的问题

解决引入antd样式无效问题

刚开始配置的时候,发现了一个如果同时引入css modules和按需引入antd,antd样式无效的问题

官网给出的按需加载解决方案,需要先安装babel-plugin-import

  • babel-loader的query/options字段加入
plugins: [
  [  "import",{libraryName: "antd", style: "css"}] // antd按需加载
]
  • webpack中plugins字段这样配置
module: {
  rules: [
    {// 通过babel准换JSX和ES6的代码
      test: /(\.jsx|\.js)$/,
      loader: 'babel-loader',
      exclude: /node_modules/,
      query:
      {
        presets:["env", "react"],
        plugins: [
          [  "import",{libraryName: "antd", style: "css"}] // antd按需加载
        ]
      }
    },
    {// CSS处理
      test: /\.css$/,
      loader: "style-loader!css-loader?modules",
      exclude: /node_modules/,
    }
  ]
}

测试后发现还是不行

解决办法

如果同时需要使用antd和css modules,处理样式时,需要分别处理

webpack加入以下处理

{// CSS处理
  test: /\.css$/,
  loader: "style-loader!css-loader?modules",
  exclude: /node_modules/,
},
{// antd样式处理
  test:/\.css$/,
  exclude:/src/,
  use:[
      { loader: "style-loader",},
      {
          loader: "css-loader",
          options:{
              importLoaders:1
          }
      }
  ]
},

引入less

由于后期要修改ant上的样式,根据官网上给出的提示,必须加装less格式

image

继续在webpack加入以下处理

{// less样式处理
  test: /\.less$/,
  use: 
  [
    "style-loader", 
    {
      loader: 'css-loader', 
      options: {
        sourceMap: 1,
        modules:true
      }
    }, 
    {
      loader: "postcss-loader",
      options: {           // 如果没有options这个选项将会报错 No PostCSS Config found
        plugins: (loader) => [
            require('autoprefixer')(), //CSS浏览器兼容
        ]
      }
    },
    {
      loader: "less-loader",
      options: {
        modifyVars: {
          'primary-color': '#1DA57A',
          'link-color': '#1DA57A',
          'border-radius-base': '2px',
        },
        javascriptEnabled: true,
      }
    }
  ]
},

好了,可以开森的npm组件了

Github Repo

查看我创建的前端React呼出菜单组件

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant