## 前言
基于前面的了解或者公司内部的刚需,可能搭建cnpm仓库已经变成了你必须会的知识点。跟着我一起去服务器部署一个私有的cnpm仓库吧。
### 环境要求
* 系统要求:mac或者linux(服务器基本都是linux的)
* nodejs:4.2.3 以上版本
### 基本安装
* nodejs
  ~~~
  curl -sL https://rpm.nodesource.com/setup_7.x | bash -  (脚本)
  yum install -y nodejs
  yum install -y gcc-c++ make
  ~~~
*  安装mysql
1.  检测并卸载已有的
    ~~~
      rpm -qa | grep mariadb
      rpm -e --nodeps mariadb/mysql
    ~~~
2. 安装mysql-server
2.1 在/etc/yum.repos.d/目录创建MariaDB.repo文件,内容如下:
    ~~~
     # MariaDB 5.5 CentOS repository list - created 2014-03-04 11:20 UTC  
    # http://mariadb.org/mariadb/repositories/  
    [mariadb]  
    name = MariaDB  
    baseurl = http://yum.mariadb.org/5.5/centos6-amd64  
    gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB  
    gpgcheck=1 
    ~~~
	2.2 安装对应包
    ~~~
      sudo yum -y install mariadb-server MariaDB-client
    ~~~
   2.3 启动服务
   ~~~
   //如果你是centos 系统
   systemctl start mariadb.service
   //如果你是GUN/linux ,只有service服务
   service mysql start
   //修改数据库密码,默认是空的
   mysqladmin -u root password "passwd"
   ~~~
   2.4 相关命令的拓展
      ~~~
      //centos 系统
      systemctl start mariadb #启动服务
    systemctl enable mariadb #设置开机启动
    systemctl restart mariadb #重新启动
    systemctl stop mariadb.service #停止MariaDB
    // gun
    service xxxx start/stop/enable/restart
      ~~~
   
      
* 安装git并检出cnpmjs项目
     ~~~
     //安装git 下载cnpmjs的git项目 
      yum install git
      git clone git://github.com/fengmk2/cnpmjs.org.git $HOME/cnpmjs.org
      cd cnpmjs.org
     //用户登陆 修改相关的库表信息
      Mysql -u root -p
      create database cnpmjs;
      use cnpmjs;
     source docs/db.sql【db.sql位于cnpmjs.org/docs/db.sql】
     //允许外部链接数据库(如果 你想查看数据库的情况有必要设置)
     grant all privileges on *.* to root@'%' identified by 'password';
     //根据自己的需要修改index的配置文件
    vim config/index.js 
     ~~~
### 使用须知
* cnpm提供两个端口:7001和7002,其中7001用于NPM的注册服务,7002用于Web访问。
* bindingHost为安装cnpm的服务器ip地址,也就是在浏览器中只能通过访问http://192.168.0.234来访问cnpm以及获取npm的注册服务。
修改本地下载地址(registryHost:r.cnpmjs.org修改为192.168.0.129:7001)
* 安装依赖
    ~~~
    //持久使用
    npm config set registry https://registry.npm.taobao.org
    // 配置后可通过下面方式来验证是否成功
    npm config get registry// 或
    npm info express
    //进入./cnpmjs.org,执行npm install
    npm install
    ~~~
* 启动服务
node dispatch.js或者“nohup node dispatch.js &”来启动。
其中nohup为在后台启动。
    ~~~
    npm run dev:调试模式启动;
    npm run test:跑测试;
    npm run start:启动 CNPM;永久的热启动
    npm run status:查看 CNPM 启动状态;
    npm run stop:停止 CNPM。
    ~~~
* 如果启动时报错:`/lib64/libc.so.6: version `GLIBC_2.14' not found`,这个是因为glibc版本过低引起的,你可以通过命令查看目前支持的版本:`strings /lib64/libc.so.6 |grep GLIBC `   ,解决办法从官网下载相关的压缩包然后编译安装,再配置到相关的目录下。
 1.  找到官网:http://www.gnu.org/software/libc/,下载2.14版本后缀为gz的压缩包,我们下载后放到root/software 下
 2. 剩下的都是命令行操作
    ~~~cmd
    //解压
    [root@jrgc130 ~]#tar zxf glibc-2.14.tar.gz
    [root@jrgc130 ~]# cd /opt/software
    [root@jrgc130 software]# tar xf glibc-2.14.tar.gz
    [root@jrgc130 software]# cd glibc-2.14
    [root@jrgc130 glibc-2.14]# mkdir build
    [root@jrgc130 glibc-2.14]# cd build
    //修改配置文件
    [root@jrgc130 build]# ../configure --prefix=/usr/local/glibc-2.14
    //安装
    [root@jrgc130 build]# make -j4
    [root@jrgc130 build]# make install
    //拷贝链接库
    [root@jrgc130 build]# cd /usr/local/glibc-2.14/lib
	[root@jrgc130 lib]# cp libc-2.16.so /lib64/
    //创建链接
    [root@jrgc130 lib]# cd /lib64
	[root@jrgc130 lib64]# rm -rf libc.so.6
    //复制相关文件到so
    [root@example lib64]# /sbin/sln libc-2.14.so /lib64/libc.so.6
    //运行strings /lib64/libc.so.6 |grep GLIBC 可以查看最新支持版本为2.14,问题解决。
    ~~~
* 测试是否启动成功
    ~~~
    在浏览器中输入:http://192.168.0.234:7002/,如果出现:
    发布私有包
    npm config set registry https://registry.npm.taobao.org
    安装cnpm客户端
    curl -sL https://rpm.nodesource.com/setup_7.x | bash -  (脚本)
    yum install -y nodejs
    sudo npm install cnpm -g
    更改默认的registry,指向私有的registry
    cnpm set registry http://192.168.0.234:7001
    ~~~
    
* 用npm账号登录你的私有registry
这里的账号中www.npmjs.com的账号,没有请注册(admin登录)
    ~~~
    $ cnpm login
    Username: admin
    Password: npm0816@zjkj.com
    Email: (this IS public) admin@cnpmjs.org
    ~~~
    
    
* 如果过程中遇到不能同步或者下载自己的模块 ,可以修改/config/index.js 文件
    > enableAbbreviatedMetadata: true
### 创建私有测试包
* 生成测试包
    ~~~
    $ cd /tmp
    $ mkdir helloworld && cd helloworld
    $ cnpm init
    name: @cjt/helloworld
    version: 1.0.0
    ~~~
* 生成package.json(产出文件) :
    ~~~
    {
      "name": "@cjt/helloworld",
      "version": "1.0.0",
      "description": "my first scoped package",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "author": "",
      "license": "ISC"
    }
    ~~~
* 注意事项
1. 注意,包名helloworld前必须要以公司名@cjt为前缀, @cjt在 config/index.js的scopes中配置
    ~~~
      // registry scopes, if don't set, means do not support scopes,你可以设置为kkl
      scopes: [ '@cjt','@cnpm', '@cnpmtest', '@cnpm-test' ],
    ~~~
2. 其余管理员账号权限分配必须二次开发,修改 `middleware/publishable.js` ,也可以直接修改index.js中的文件,默认的管理员是admin ; 
3. 注册并登陆用户:
	
3. 发布与同步(见cnpm入门)
    ~~~
    发布
    cnpm publish
    通过浏览器访问:http://192.168.0.129:7002/ 可查看和操作私有CNPM服务器
    从默认源同步gulp
    cnpm sync gulp
    下载
    cnpm install gulp
    ~~~
## 配置文件(config/index.js) 
   ~~~
    'use strict';
    var mkdirp = require('mkdirp');
    var copy = require('copy-to');
    var path = require('path');
    var fs = require('fs');
    var os = require('os');
    var version = require('../package.json').version;
    var root = path.dirname(__dirname);
    var dataDir = path.join(process.env.HOME || root, '.cnpmjs.org');
    var config = {
      version: version,
      dataDir: dataDir,
      /**
       * Cluster mode 是否启用 cluster-worker 模式启动服务,默认 false,生产环节推荐为 true; 利用多核
       */
      enableCluster: true,
      numCPUs: os.cpus().length,
      /*
       * server configure  服务器的基本设置,ip以及请求以及访问端口(必须设置)
       */
      registryPort: 7001,
      webPort: 7002,
      bindingHost: '10.0.0.141', // only binding on 127.0.0.1 for local access
      // debug mode
      // if in debug mode, some middleware like limit wont load
      // logger module will print to stdout
      debug: process.env.NODE_ENV === 'development',
      // page mode, enable on development env
      pagemock: process.env.NODE_ENV === 'development',
      // session secret
      sessionSecret: 'cnpmjs.org test session secret',
      // max request json body size
      jsonLimit: '10mb',
      // log dir name
      logdir: path.join(dataDir, 'logs'),
      // update file template dir
      uploadDir: path.join(dataDir, 'downloads'),
      // web page viewCache
      viewCache: false,
      // config for koa-limit middleware
      // for limit download rates
      limit: {
        enable: false,
        token: 'koa-limit:download',
        limit: 1000,
        interval: 1000 * 60 * 60 * 24,
        whiteList: [],
        blackList: [],
        message: 'request frequency limited, any question, please contact fengmk2@gmail.com',
      },
      enableCompress: false, // enable gzip response or not
      // default system admins,(管理员必须设置为自己清楚的,只有管理员可以删除模块,配置需要重启)
      admins: {
        // name: email
        fengmk2: 'fengmk2@gmail.com',
        admin: 'admin@cnpmjs.org',
        dead_horse: 'dead_horse@qq.com',
      },
      // email notification for errors
      // check https://github.com/andris9/Nodemailer for more informations
      mail: {
        enable: false,
        appname: 'cnpmjs.org',
        from: 'cnpmjs.org mail sender <adderss@gmail.com>',
        service: 'gmail',
        auth: {
          user: 'address@gmail.com',
          pass: 'your password'
        }
      },
      logoURL: 'https://os.alipayobjects.com/rmsportal/oygxuIUkkrRccUz.jpg', // cnpm logo image url
      adBanner: '',
      customReadmeFile: '', // you can use your custom readme file instead the cnpm one
      customFooter: '', // you can add copyright and site total script html here
      npmClientName: 'cnpm', // use `${name} install package`,(默认的安装命令符号)
      packagePageContributorSearch: true, // package page contributor link to search, default is true
      // max handle number of package.json `dependencies` property
      maxDependencies: 200,
      // backup filepath prefix
      backupFilePrefix: '/cnpm/backup/',
      /**
       * database config(数据库配置文件,必须设置的)
       */
      database: {
        db: 'cnpmjs',
        username: 'root',
        password: 'kkl123456',
        // the sql dialect of the database
        // - currently supported: 'mysql', 'sqlite', 'postgres', 'mariadb'
        dialect: 'mariadb',
        // custom host; default: 127.0.0.1
        host: '127.0.0.1',
        // custom port; default: 3306
        port: 3306,
        // use pooling in order to reduce db connection overload and to increase speed
        // currently only for mysql and postgresql (since v1.5.0)
        pool: {
          maxConnections: 10,
          minConnections: 0,
          maxIdleTime: 30000
        },
        // the storage engine for 'sqlite'
        // default store into ~/.cnpmjs.org/data.sqlite
        storage: path.join(dataDir, 'data.sqlite'),
        logging: !!process.env.SQL_DEBUG,
      },
      // package tarball store in local filesystem by default(文件系统,可以默认,可以用其他云服务器)
      nfs: require('fs-cnpm')({
        dir: path.join(dataDir, 'nfs')
      }),
      // if set true, will 302 redirect to `nfs.url(dist.key)`
      downloadRedirectToNFS: false,
      // registry url name(模块下载请求地址,必须设置)
      registryHost: '10.0.0.141:7001',
      /**
       * registry mode config
       */
      // enable private mode or not(必须设置,false允许其他人发布,否则只有管理员)
      // private mode: only admins can publish, other users just can sync package from source npm
      // public mode: all users can publish
      enablePrivate: false,
      // registry scopes, if don't set, means do not support scopes(私有模块前缀,必须设置)
      scopes: [ '@kkl'],
      // some registry already have some private packages in global scope
      // but we want to treat them as scoped private packages,
      // so you can use this white list.
      privatePackages: [],
      /**
       * sync configs
       */
      // the official npm registry(官方请求地址,一般不用修改)
      // cnpm wont directly sync from this one
      // but sometimes will request it for some package infomations
      // please don't change it if not necessary
      officialNpmRegistry: 'http://registry.npm.taobao.org',
      officialNpmReplicate: 'https://replicate.npmjs.com',
      // sync source, upstream registry(同步模块的地址,设置为阿里镜像建议)
      // If you want to directly sync from official npm's registry
      // please drop them an email first
      sourceNpmRegistry: 'http://registry.npm.taobao.org',
      // upstream registry is base on cnpm/cnpmjs.org or not
      // if your upstream is official npm registry, please turn it off
      sourceNpmRegistryIsCNpm: true,
      // if install return 404, try to sync from source registry(模块没有,从远程更新下载,必须设置)
      syncByInstall: true,
      // sync mode select(同步模式,同步已有模块即可)
      // none: do not sync any module, proxy all public modules from sourceNpmRegistry
      // exist: only sync exist modules
      // all: sync all modules
      syncModel: 'exist', // 'none', 'all', 'exist'
      syncConcurrency: 1,
      // sync interval, default is 10 minutes(10ms同步一次)
      syncInterval: '10m',
      // sync polular modules, default to false(不同步热门模块)
      // because cnpm can't auto sync tag change for now
      // so we want to sync popular modules to ensure their tags
      syncPopular: false,
      syncPopularInterval: '1h',
      // top 100
      topPopular: 100,
      // sync devDependencies or not, default is false
      syncDevDependencies: false,
      // changes streaming sync
      syncChangesStream: false,
      handleSyncRegistry: 'http://127.0.0.1:7001',
      // badge subject on http://shields.io/
      badgePrefixURL: 'https://img.shields.io/badge',
      badgeSubject: 'cnpm',
      // custom user service, @see https://github.com/cnpm/cnpmjs.org/wiki/Use-Your-Own-User-Authorization
      // when you not intend to ingegrate with your company's user system, then use null, it would
      // use the default cnpm user system
      userService: null,
      // always-auth https://docs.npmjs.com/misc/config#always-auth
      // Force npm to always require authentication when accessing the registry, even for GET requests.
      alwaysAuth: false,
      // if you're behind firewall, need to request through http proxy, please set this
      // e.g.: `httpProxy: 'http://proxy.mycompany.com:8080'`
      httpProxy: null,
      // snyk.io root url
      snykUrl: 'https://snyk.io',
      // https://github.com/cnpm/cnpmjs.org/issues/1149(针对某个补丁文件的修复,必须设置)
      // if enable this option, must create module_abbreviated and package_readme table in database
      enableAbbreviatedMetadata: true,
      // global hook function: function* (envelope) {}
      // envelope format please see https://github.com/npm/registry/blob/master/docs/hooks/hooks-payload.md#payload
      globalHook: null,
    };
    if (process.env.NODE_ENV === 'test') {
      config.enableAbbreviatedMetadata = true;
    }
    if (process.env.NODE_ENV !== 'test') {
      var customConfig;
      if (process.env.NODE_ENV === 'development') {
        customConfig = path.join(root, 'config', 'config.js');
      } else {
        // 1. try to load `$dataDir/config.json` first, not exists then goto 2.
        // 2. load config/config.js, everything in config.js will cover the same key in index.js
        customConfig = path.join(dataDir, 'config.json');
        if (!fs.existsSync(customConfig)) {
          customConfig = path.join(root, 'config', 'config.js');
        }
      }
      if (fs.existsSync(customConfig)) {
        copy(require(customConfig)).override(config);
      }
    }
    mkdirp.sync(config.logdir);
    mkdirp.sync(config.uploadDir);
    module.exports = config;
    config.loadConfig = function (customConfig) {
      if (!customConfig) {
        return;
      }
      copy(customConfig).override(config);
    };
~~~
    
### 参考测试文档
* [cnpm配置](http://blog.csdn.net/xs20691718/article/details/51898164)
* [cnpm官网文档介绍](https://github.com/cnpm/cnpmjs.org/wiki)
                    
        - 前端工程化
 - 架构总纲
 - 001
 - 美团技术架构
 - 前端工程化说明
 - 历史背景说明
 - 架构说明
 - 前端工程化技术栈
 - 技术文档说明
 - 功能模块说明
 - 前端模块管理器简介
 - 框架对比分析
 - vue&react&ng对比分析(一)
 - vue&react&ng对比分析(二)
 - vue&react&ng对比分析(三)
 - 工程化专题系列
 - 需要解决的问题
 - 001
 - 002
 - 003
 - 常见代码错误
 - jslint中常见的错误
 - css规范常见错误
 - html规范常见错误
 - 工程化目录
 - 工程化初始化
 - 项目构建流程
 - 项目打包优化
 - 上线与迭代注意事项
 - 前端部署发布
 - jetkins部署
 - 部署需求整理
 - 前端监控
 - 工程化实践指南
 - dock持续部署
 - 系列文章
 - 插拔式前端的设计
 - 其他实践
 - 工程化的前端管理
 - 宋小菜借鉴
 - 大前端团队介绍
 - 人员组成
 - 人员发展
 - 研发流程
 - 任务分类
 - 前端基础建设与架构
 - 技术栈以及技术方案
 - 业务目录大纲
 - 前端大纲
 - api管理
 - 后端api工具
 - 前端easymock
 - api拦截与代理
 - api优化
 - api请求时长策略设计
 - 前端架构专题
 - 架构专题一
 - 产品原型对接
 - 与ui对接
 - 图片专题
 - 图片工程化大纲
 - 图片优化
 - 图标字体
 - 图标字体vs雪碧图
 - 工程化的前端矩阵
 - 蚂蚁金服前端矩阵分享
 - BFF架构
 - 概念解析
 - 前端脚手架
 - 初始化项目
 - 个性化配置
 - 部署与发布
 - 性能优化专题
 - http专题
 - https常识
 - http优化1
 - http优化2
 - http优化3
 - http缓存
 - 常规web性能优化攻略
 - 性能优化大纲
 - 样式优化
 - js优化
 - 第三方依赖优化
 - 代码分割优化
 - 图片优化
 - 打包优化
 - 服务器优化
 - 缓存优化
 - 交互优化
 - pc事件优化
 - 手机事件优化
 - 推荐文章
 - 01
 - 前端安全专题
 - 前端安全大纲
 - 前端第三方库
 - seo优化
 - web框架的对比
 - 001
 - 学习资源
 - 珠峰前端架构
 - npm教程
 - npm入门
 - cnpm入门
 - cnpm搭建
 - 你该知道的js模块
 - browserSync
 - opn
 - js-cookie
 - npm-script进阶
 - 入门篇
 - 进阶篇
 - 高阶篇
 - 实践篇
 - yarn入门
 - nodejs教程
 - axios&&fetch
 - xhr
 - axios
 - fetch
 - babel专题
 - babel入门
 - profill入门
 - nodejs入门
 - 快速入门
 - 大纲介绍
 - node基础
 - global obj
 - assert断言
 - procss-进程
 - child_process子进程
 - cluster集群
 - console控制台
 - crypto-加密
 - dgram-数据报
 - dns-域名服务器
 - error-异常
 - events-事件
 - global-全局变量
 - http-基本协议
 - https-安全协议
 - modules-模块
 - os-操作系统
 - path-路径
 - querystring-查询字符串
 - readline-逐行读取
 - fs-文件系统
 - net-网络操作
 - 命令行工具
 - 内存泄露
 - 代码的组织与部署
 - 异步编程
 - orm模块
 - 异步编程解决方案
 - node-lessons
 - 环境准备
 - nodejs实践
 - 项目搭建
 - 异步优化
 - 创建web和tcp服务器
 - 终端问答程序
 - 爬虫系统
 - mongleDb
 - mongoDB简介
 - 基本使用
 - 实用技巧
 - 汇总001
 - 饿了么后台搭建
 - nodejs干货
 - 沪江基于node的实践
 - 苏宁基于nodejs优化
 - 基于nodejs开发脚手架
 - 书籍干货
 - 深入浅出nodejs
 - 异步I/O(一)
 - gulp教程
 - gulp入门
 - gulp常用插件(1)
 - gulp常用插件(2)
 - gulp创建目录
 - 经验普及贴
 - webpack教程
 - webpack入门
 - 简单入门
 - entry配置
 - output配置
 - 插件使用01
 - 插件使用02
 - loader使用
 - dev-server介绍
 - 构建css
 - css模块化
 - 使用less和sass
 - 构建图片
 - 引入字体
 - babel配置攻略
 - eslint
 - 001
 - webpack进阶
 - 分不同文件检出
 - 优化打包大小
 - 优化打包速度
 - 自定义配置
 - 单页以及多页如何配置
 - 优化实践
 - 文章导读
 - 001
 - 优化指南
 - 参考列表
 - webpack4
 - 多入口程序构建
 - 参考教程
 - 项目实践
 - 环境区分
 - 常见问题
 - 解读webpack
 - 从vuejs权威指南中解决
 - 深入浅出webpack
 - rollup
 - 入门
 - parcel
 - 入门篇
 - express教程
 - nuxt教程
 - 入门
 - 基本入门
 - koa教程
 - koa基本入门
 - koa开发注意事项
 - koa实践指南
 - 关于路由
 - koa优化指南
 - 001
 - Vuejs
 - vuejs入门系列
 - vue-cli入门
 - vue2基本认识
 - vuejs入门教程
 - 样式绑定
 - vuex入门学习笔记
 - vue组件生命周期
 - 组件的使用
 - vue-router入门
 - vue-filter
 - 计算属性使用
 - 开发注意事项
 - mixins
 - 组件通讯
 - vuejs进阶
 - 进阶资源
 - router进阶
 - 官网介绍
 - 前进与后退优化
 - keep-alive基本使用
 - keep-alive原理详解
 - 钩子函数进阶
 - 计算属性&监听&方法
 - vue服务端渲染技术
 - 项目实践之路
 - 实践大纲
 - 插槽专题篇
 - vue-cli升级
 - 进阶入门
 - vuejs架构
 - nuxt
 - vuejs项目实践
 - vue实践常见问题
 - 001
 - 002
 - 003
 - 004
 - 005
 - 改造api参数探索
 - 007
 - 008
 - 009
 - 010
 - 项目技术栈
 - vue性能问题以及优化方案
 - vue-spa应用的理解
 - vue-ssr的部署与使用
 - 滴滴出行实践案例
 - 2.0重构
 - vue-element-admin实践
 - 准备工作
 - 菜单设计
 - 权限设计
 - 依赖模块
 - vue-betterScroll
 - 性能优化懒加载
 - 京东组件实践
 - vue2项目小结
 - vue探索与实践
 - 去哪实践
 - 介绍
 - 饿了么项目实践
 - 项目解析
 - vue骨架屏实践
 - vue生态推荐
 - ui框架
 - elementUI
 - 001
 - 002
 - VUE-material
 - vant-ui
 - 解读入门
 - iview
 - 使用问题汇总
 - vux
 - mint-ui
 - loadmore
 - vue资源导航
 - vueconf
 - 源码解读
 - vm
 - 双向绑定
 - 基本原理
 - 数组双向绑定
 - 报错机制
 - 封装方法
 - 运行环境
 - 入门
 - 指令
 - vue-router解读
 - util
 - vue-props
 - 流程逻辑
 - 推荐文章
 - 源码解读
 - 文章导读
 - 001
 - vuejs实战
 - 基础篇
 - 进阶篇
 - 实践篇
 - 面试专题
 - angularjs教程
 - angularjs入门系列
 - 基本入门
 - ng2入门
 - ng进阶
 - ng项目实践
 - 源码解读
 - typescript
 - reactjs教程
 - reactjs入门系列
 - react的基本入门
 - react组件
 - virtalDom认识
 - react-cli入门
 - react组件的生命周期
 - 基本知识点
 - react-router教程
 - react进阶
 - 基本实践
 - react加载性能优化指南
 - react属性封装
 - 进阶45讲
 - 01概述
 - 02jsx
 - 06高阶组件&函数子组件
 - contextApi
 - react-router
 - 入门章节
 - 进阶
 - 高阶组件
 - react进阶组件
 - 基本介绍
 - render props
 - render props的封装
 - render props getter
 - react-native入门
 - 源码解读
 - 001
 - 002-reactDemo
 - 参考教程
 - 参考教程1
 - 了解react-hooks
 - ui框架
 - pc端ui框架推荐
 - 项目实践
 - weatherApp
 - 001
 - 002
 - 不同生命周期使用场景
 - react项目结构和组件的命名
 - 常见问题解答
 - 参考书籍
 - react全栈
 - 前言
 - react与redux进阶
 - 常见误解
 - 反模式
 - react设计模式与最佳实践
 - 7美化组件
 - 7.2行内样式
 - 7.4css模块
 - 深入react技术栈
 - react学习手册
 - 序
 - mobx教程
 - 入门
 - 大佬推荐
 - 001
 - react面试
 - 001
 - linux教程
 - linux入门
 - 基本入门
 - 文件管理
 - 文件传输
 - 文档编辑
 - 磁盘管理
 - 磁盘维护
 - 网络通讯
 - 系统管理
 - 系统设置
 - 备份压缩
 - 设备管理
 - 查看系统信息
 - linux其他
 - webhook
 - rsync入门教程
 - ssh免登陆设置
 - 安装nodejs
 - nginx教程
 - 入门教程
 - 安装
 - 基本配置
 - 服务基本使用
 - 高性能nginx
 - 001
 - pm2教程
 - shell教程
 - 入门大纲
 - echo命令
 - 参考文献
 - linux常用命令2
 - linux常见问题
 - 001
 - python
 - 入门教程
 - 机器学习
 - 准备工作
 - 服务器常识
 - tomcat
 - 入门常识
 - iis
 - redis教程
 - 入门第一篇
 - redis进阶
 - 项目实践
 - redis使用问题
 - mongleDB
 - 入门
 - 使用进阶
 - 项目实践
 - 常见问题
 - electron
 - 入门系列
 - 前言
 - 小程序
 - 入门
 - 准备工作
 - 路由
 - 参考文档
 - 001
 - 小程序开发--双路视频调研
 - 准备工作
 - 参考资源
 - 参考网址
 - docker
 - 入门
 - 基本认识
 - 安装与使用
 - docker安装nginx
 - docker安装jetkins(1)
 - docker部署jenkins(2)
 - 进阶
 - 实践总结
 - docker群分享
 - docker部署前端应用
 - 文章导读
 - docker其他
 - 网络安全
 - 入门
 - 大纲
 - 项目解析
 - schoolpal.web
 - 功能模块大纲
 - 目录结构大纲
 - 前端国际化
 - 国际化方案
 - 其他
 - bower入门教程
 - weex
 - 入门
 - memcached
 - 入门
 - sails
 - 入门
 
