react組件化開發發佈到npm

1.項目目錄css

  • build:webpack打包用(開發環境、發佈環境)
  • example:開發環境的模板頁
  • lib:打包好的文件夾(用於發佈到npm上)
  • src:想要封裝的公共組件
  • .babelrc:處理es6語法
  • package.json:打包的依賴文件,管理項目模塊包

開發環境配置(webpack.dev.config.js)

const path = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: path.join(__dirname, '../example/main.js'),
  devtool: 'cheap-module-eval-source-map',
  output: {
    path: path.join(__dirname, '../dist'),
    filename: 'bundle.js'
  },
  plugins: [ // 插件
    new htmlWebpackPlugin({
      template: path.join(__dirname, '../example/index.html'),
      filename: 'index.html'
    })
  ],
  module: {
    rules: [
      { test: /\.css$/, use: ['style-loader', 'css-loader'] }, // 若是想要啓用 CSS 模塊化,能夠爲 css-loader 添加 modules 參數便可
      { test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] },
      { test: /\.(jpg|png|gif|bmp|jpeg)$/, use: 'url-loader?limit=5000' },
      { test: /\.(ttf|eot|svg|woff|woff2)$/, use: 'url-loader?limit=5000' },
      { test: /\.jsx?$/, use: 'babel-loader', exclude: /node_modules/ }
    ]
  }
}

打包環境配置(webpack.pub.config.js)

const path = require('path')
// 導入每次刪除文件夾的插件
const cleanWebpackPlugin = require('clean-webpack-plugin')
const webpack = require('webpack')
// 導入抽取CSS的插件
const ExtractTextPlugin = require("extract-text-webpack-plugin")
// 導入壓縮CSS的插件
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')

module.exports = {
  entry:  path.join(__dirname, '../src/index.js'),
  devtool: 'cheap-module-source-map',
  output: {
    path: path.join(__dirname, '../lib'),
    filename: 'index.js',
    libraryTarget: 'umd',  //發佈組件專用
    library: 'ReactCmp',
  },
  plugins: [ // 插件
    new cleanWebpackPlugin(['./lib']),
    new webpack.optimize.UglifyJsPlugin({
      compress: { // 配置壓縮選項
        warnings: false // 移除警告
      }
    }),
    new ExtractTextPlugin("css/styles.css"), // 抽取CSS文件
    new OptimizeCssAssetsPlugin()// 壓縮CSS的插件
  ],
  module: {
    rules: [
      {
        test: /\.css$/, use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: "css-loader",
          publicPath: '../' // 指定抽取的時候,自動爲咱們的路徑加上 ../ 前綴
        })
      },
      {
        test: /\.scss$/, use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: ['css-loader', 'sass-loader'],
          publicPath: '../' // 指定抽取的時候,自動爲咱們的路徑加上 ../ 前綴
        })
      },
      { test: /\.(jpg|png|gif|bmp|jpeg)$/, use: 'url-loader?limit=5000&name=images/[hash:8]-[name].[ext]' },
      { test: /\.(ttf|eot|svg|woff|woff2)$/, use: 'url-loader?limit=5000&name=images/[hash:8]-[name].[ext]' },
      { test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ }
    ]
  }
}

組件

// button.js 封裝的button組件
import React, { Component } from 'react';
import PropTypes from 'prop-types';
export default class Button extends Component {
  constructor(props) {
    super(props)
  }
  static propTypes = {
    /**
     * @title 樣式定義
     * @description 經過CSS定義按鈕的樣式
     */
    style: PropTypes.shape({
      color: PropTypes.string,
      fontSize: PropTypes.number,
      background: PropTypes.string,
      padding: PropTypes.string,
    }),
  };

  static defaultProps = {
    style: {
      color: '#fff',
      background: 'green',
      padding: '4px',
    },
  };
  render() {
    const style = this.props.style;
    return (
      <button style={style}>{this.props.children}</button>
    );
  }
}

// index.js輸出文件
import React from 'react';
import RCmp from './app';
import Button from './button';
import Photo from './photo';
import './app.scss';
RCmp.Button = Button;
RCmp.Photo = Photo;
export default RCmp;
export {
  Button,
  Photo,
  RCmp,
}

實時調試

npm run dev

package.json

{
  "name": "react-cmp",
  "version": "0.0.4",
  "description": "初始化開發react組件",
  "main": "lib/index.js",
  "files": [
    "build",
    "example",
    "src"
  ],
  "repository": {
    "type": "git",
    "url": "git+https://github.com/lydxwj/react-cmp.git"
  },
  "homepage": "https://github.com/lydxwj/react-cmp",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server --config ./build/webpack.dev.config.js --open --port 3000 --hot",
    "pub": "webpack --config ./build/webpack.pub.config.js",
    "prepublish": "npm run pub"
  },
  "keywords": [ "react", "component", "react-cmp" ],
  "author": "author",
  "license": "MIT",
  "dependencies": {
    "prop-types": "^15.6.0",
    "react": "^16.1.1",
    "react-dom": "^16.1.1"
  },
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-plugin-import": "^1.6.2",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-preset-env": "^1.6.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-0": "^6.24.1",
    "clean-webpack-plugin": "^0.1.17",
    "css-loader": "^0.28.7",
    "extract-text-webpack-plugin": "^3.0.2",
    "file-loader": "^1.1.5",
    "html-webpack-plugin": "^2.30.1",
    "node-sass": "^4.6.0",
    "optimize-css-assets-webpack-plugin": "^3.2.0",
    "sass-loader": "^6.0.6",
    "style-loader": "^0.19.0",
    "url-loader": "^0.6.2",
    "webpack": "^3.8.1",
    "webpack-dev-server": "^2.9.4"
  }
}

package.json 簡要介紹html

  • name - 包名;
  • version - 包的版本號;
  • description - 包的描述;
  • homepage - 包的官網 url;
  • author - 包的做者姓名;
  • contributors - 包的其餘貢獻者姓名;
  • dependencies - 依賴包列表。若是依賴包沒有安裝,npm 會自動將依賴包安裝在 node_module 目錄下;
  • repository - 包代碼存放的地方的類型,能夠是 git 或 svn,git 可在 Github 上;
  • main - main 字段指定了程序的主入口文件,require('moduleName') 就會加載這個文件。這個字段的默認值是模塊根目錄下面的 index.js;
  • keywords - 關鍵字;

發佈

新建一個文件,名爲.npmignore,是不須要發佈到npm的文件和文件夾,規則和.gitignore同樣。若是你的項目底下有.gitignore可是沒有.npmignore,那麼會使用.gitignore裏面的配置。node

npm run pub

引入

iimport React from 'react';
import PropTypes from 'prop-types';
import {
  modal
} from 'math_manage'
import AutoSuggest from 'react-tiny-autosuggest';
import MyApp,{Button,Photo,} from 'react-cmp-master';

class App extends React.Component {
  static defaultProps = {}
  static propTypes = {}

  constructor(props) {
    super(props);
  }
  componentWillMount() {
    document.title = "1666";
    console.log(modal);
  }
  render() {
    const suggestions = ['foo', 'bar'];  
    const handleSelect = selection => {console.log(selection)};

    let input;
    const handleSubmit = () => console.log(input.value);
    return (
      <div> 
        <AutoSuggest
          suggestions = {suggestions}
          onSelect = {handleSelect}
          placeholder = "whatever..." 
        />
        <MyApp text='Hello react組件'/>
        <Button/>
        <Photo src={'https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=2198746125,2255961738&fm=27&gp=0.jpg'}/>
      </div>
    )
  }
}

export default App;

版本管理

分爲三個版本
  • 主版本號(A):當你作了不兼容的 API 修改,0表示處於開發階段;
  • 次版本號(B):當你作了向下兼容的功能性新增;
  • 修訂號(C):當你作了向下兼容的問題修正。

~容許小版本迭代react

  • 若是有缺省值,缺省部分任意迭代;
  • 若是沒有缺省值,只容許補丁即修訂號(Patch)的迭代

eg.:webpack

  • ~1.2.3:>=1.2.3 <1.3.0
  • ~1.2:>=1.2.0 < 1.3.0(至關於1.2.x)
  • ~1:>=1.0.0 <2.0.0(至關於1.x)
  • ~0.2.3:>=0.2.3 <0.3.0
  • ~0.2:>=0.2.0 <0.3.0(至關於0.2.x)
  • ~0:>=0.0.0 <1.0.0(至關於0.x)

^容許大版本迭代git

  • 容許從左到右的第一段不爲0那一版本位+1迭代(左閉右開);
    若是有缺省值,且缺省值以前沒有不爲0的版本位,則容許缺省值的前一位版本+1迭代
    eg.:
  • ^1.2.3:>=1.2.3 <2.0.0
  • ^0.2.3:>=0.2.3 <0.3.0
  • ^0.0.3:>=0.0.3 <0.0.4
  • ^1.2.x:>=1.2.0 <2.0.0
  • ^0.0.x:>=0.0.0 <0.1.0
  • ^0.0:>=0.0.0 <0.1.0
  • ^1.x:>=1.0.0 <2.0.0
  • ^0.x:>=0.0.0 <1.0.0

每一個npm包都有一個package.json,若是要發佈包的話,package.json裏面的version字段就是決定發包的版本號了。es6

version字段是這樣一個結構: ‘0.0.1’,是有三位的版本號。分別是對應的version裏面的:major, minor, patch。
也就是說當發佈大版本的時候會升級爲 1.0.0,小版本是0.1.0,一些小修復是0.0.2。github

鎖定(控制)版本

package-lock.json或是yarn.lock。web

在npm的版本>=5.1的時候,package-lock.json文件是自動打開的,意味着會自動生成,
package-lock.json(官方文檔)能夠理解爲/node_modules文件夾內容的json映射,並可以感知npm的安裝/升級/卸載的操做。能夠保證在不一樣的環境下安裝的包版本保持一致。聽上去很不錯哈,實際使用中,大部分它的表現確實不錯,但是如上述問題:我手動修改了package.json文件內依賴的版本,package-lock.json就沒那麼聰明(至少目前是,將來會不會變聰明就不可知了),且不會變化。因而BOOOOOOM~~~~npm

若是你真的想保證你的包版本在各個環境都是同樣的話,請修改下package.json中的依賴,去掉默認前面的^,固然這樣的話,你就無法自動享受依賴包小版本的修復了,問題來了,在什麼狀況下選擇哪種呢?

在依賴包嚴格按照版本規範來開發的,你可使用^來享受包的最新功能和修復。這也是推薦的。
在你不可知或已知依賴包不是那麼規範的狀況下,或許它在一個小版本(patch)作出不兼容更改(不兼容更改在beta等先行版本中必定[墨菲定律]會發生),那麼這個時候,你應該把這個依賴包的版本在package.json上鎖住版本,而不該該把它交給package-lock.json來處理
記住一點,絕對不要在生成環境下使用beta等先行版本依賴包,由於若是那是你的私有項目,它會在將來的某一刻坑害了你,若是這是你的共有項目,那麼,它必定會在將來的某一刻對你的全部用戶作出致命的坑害行爲!(beta包就是不負責任的流氓包,玩家爽就好 ^o^)

  • 最後:rm -rf node_modules/ && npm install大法在你使用package-lock的狀況下,請更換爲:rm -rf node_modules && rm -rf package-lock.json && npm install。
相關文章
相關標籤/搜索