• nodejs


    npm install (the command) to work behind proxy

    config set strict-ssl false
    npm config set registry "http://registry.npmjs.org/"
    npm --proxy http://proxy_host:port install packagename
    

    下载最新稳定版本 参考joyent installation nodejs开发指南express3源码
    ---------------------------------
    安装依赖库
     Python 版本 2.5 以上
     sudo apt-get install g++ curl libssl-dev apache2-utils   
     sudo apt-get install git-core
    ---------------------------------
    源码编译安装
     tar -zxf node-v0.8.16.tar.gz
     cd node-v0.8.16
     ./configure --prefix=/opt/node
     make
     sudo make install
     #环境变量设置
     export PATH=$PATH:$NODE_HOME/bin:$NODE_HOME/lib/node_modules
     #终端中启用配置
     source /opt/profile
    ---------------------------------
    Binary安装
     cd /opt/node
     tar -zxf node-v0.8.16-linux-x64.tar.gz
     #环境变量设置
     export PATH=$PATH:$NODE_HOME/bin:$NODE_HOME/lib/node_modules
     #终端中启用配置
     source /opt/profile
    ---------------------------------
    安装NPM(最近nodejs已集成npm)
     集成npm安装
      ./configure --prefix=/opt/node/npm
      make
      sudo make install
      #环境变量设置
       export PATH=$PATH:$NPM_HOME/bin
      #终端中启用配置
       source /opt/profile
     独立安装
      curl http://npmjs.org/install.sh | sh
       or
      cd /opt/node/lib/node_modules/npm/scripts
      sh install.sh
    ---------------------------------
    命令行调试:
      node debug *.js
    远程调试:
      node --debug[=port] script.js     #脚本会正常执行不会暂停,默认情况下调试端口是 5858
      node --debug-brk[=port] script.js #调试服务器在启动后会立刻暂停执行脚本,等待调试客户端连接
      #在一个终端中
        node --debug-brk debug.js
        debugger listening on port 5858
      #在另一个终端中
        node debug 127.0.0.1:5858
      ---------------------------------
      run 执行脚本,在第一行暂停
      restart 重新执行脚本
      cont, c 继续执行,直到遇到下一个断点
      next, n 单步执行
      step, s 单步执行并进入函数
      out, o 从函数中步出
      setBreakpoint(), sb() 在当前行设置断点
      setBreakpoint(‘f()’), sb(...) 在函数f的第一行设置断点
      setBreakpoint(‘script.js’, 20), sb(...) 在 script.js 的第20行设置断点
      clearBreakpoint, cb(...) 清除所有断点
      backtrace, bt 显示当前的调用栈
      list(5) 显示当前执行到的前后5行代码
      watch(expr) 把表达式 expr 加入监视列表
      unwatch(expr) 把表达式 expr 从监视列表移除
      watchers 显示监视列表中所有的表达式和值
      repl 在当前上下文打开即时求值环境
      kill 终止当前执行的脚本
      scripts 显示当前已加载的所有脚本
      version 显示 V8 的版本
    ---------------------------------
    node-inspector是一个完全基于Node.js的开源在线调试工具
      #node-inspector使用了WebKit Web Inspector,因此只能在Chrome等WebKit内核的浏览器中使用
      命令安装:npm install -g node-inspector
      在终端中通过node --debug-brk=5858 debug.js命令连接你要除错的脚本的调试服务器
      启动 node-inspector:node-inspector
      在浏览器中打开http://127.0.0.1:8080/debug?port=5858,即可显示Web调试工具
    ---------------------------------
    process用于描述当前Node.js进程状态的对象,提供了一个与操作系统的简单接口
     argv.js:
       console.log(process.argv);
     $ node argv.js 2012 name=Eric --v "ningbo"
       [ 'node',
         '/home/work/argv.js',
         '2012',
         'name=Eric',
         '--v',
         'ningbo' ]
     ---------------------------------
     #http://nodejs.org/api/process.html
     process.nextTick(callback)的功能是为事件循环设置一项任务,Node.js会在下次事件循环调响应时调用callback
      compute()和somethingComplicated()是两个较为耗时的函数:
        function doSomething(args, callback) {
         somethingComplicated(args);
         callback();
        }
        doSomething(function onEnd() {
         compute();
        });
       ---------------------------------------
       function doSomething(args, callback) {
        somethingComplicated(args);
        process.nextTick(callback);
       }
       doSomething(function onEnd() {
        compute();
       });
     #不要使用 setTimeout(fn,0)代替 process.nextTick(callback),前者比后者效率要低得多
    ---------------------------------
     util.inherits(constructor, superConstructor)是一个实现对象间原型继承的函数
    ---------------------------------
     #http://nodejs.org/api/util.html
     #showHidden-隐藏信息  depth-最大递归的层数,null无限递归  colors-ANSI颜色编码
     util.inspect(object,[showHidden],[depth],[colors])是一个将任意对象转换为字符串的方法,通常用于调试和错误输出
    ---------------------------------
    事件发射器
     events.EventEmitter是事件发射与事件监听器功能的封装
      var events = require('events');
      var emitter = new events.EventEmitter();
      emitter.on('someEvent', function(arg1, arg2) {
        console.log('listener1', arg1, arg2);
      });
      emitter.on('someEvent', function(arg1, arg2) {
        console.log('listener2', arg1, arg2);
      });
      #当error发生时,EventEmitter规定如果没有响应的监听器,Node.js会把它当作异常,退出程序并打印调用栈
      #一般要为发射error事件的对象设置监听器,避免遇到错误后整个程序崩溃
      emitter.on('error', function() {
        console.log('error');
      });
      emitter.emit('someEvent', 'Eric', 2012);
    ---------------------------------
     文件系统-fs
    ---------------------------------
     HTTP-http
    ---------------------------------
    控制权转移:
      app.all('/user/:username', function(req, res) {
        res.send('all methods captured');
      });
      app.get('/user/:username', function(req, res) {
        res.send('user: ' + req.params.username);
      });
      #请求总是被前一条路由规则捕获,后面的规则会被忽略
      app.all('/user/:username', function(req, res, next) {
        console.log('all methods captured');
        next();#路由控制权转移给后面的规则
      });
      app.get('/user/:username', function(req, res) {
        res.send('user: ' + req.params.username);
      });
      -----------提高代码的复用程度-----------
      var users = {
        'person': {
         name: 'Eric',
         website: 'http://wen12128.cnblogs.com'
        }
      };
      app.all('/user/:username', function(req, res, next) {
        // 检查用户是否存在
        if (users[req.params.username]) {
          next();
        } else {
          next(new Error(req.params.username + ' does not exist.'));
        }
      });
      app.get('/user/:username', function(req, res) {
        // 用户一定存在,直接展示
        res.send(JSON.stringify(users[req.params.username]));
      });
      app.put('/user/:username', function(req, res) {
        // 修改用户信息
        res.send('Done');
      });
    ---------------------------------
    #更改默认资源库:
      npm config set registry "http://npm.hacknodejs.com/"
     #NPM资源库镜像:{http://registry.npmjs.vitecho.com}-{http://npm.hacknodejs.com/}
      npm --registry "http://npm.hacknodejs.com/" install underscore
    ---------------------------------
    安装supervisor:
     #监视你对代码的改动,并自动重启 Node.js
     npm install -g supervisor
    ---------------------------------
    安装express:
     #-d代表把相依性套件也一起安装
     查看安装包:npm ls
     npm install -gd express
     express --help
     express -t ejs demo
     cd demo && npm install
     REST风格的路由规则:
      GET:[获取app.get(path, callback)]请求获取指定资源。
      HEAD:请求指定资源的响应头。
      POST:[新增app.post(path, callback)]向指定资源提交数据。
      PUT:[更新app.put(path, callback)]请求服务器存储一个资源。
      DELETE:[删除app.delete(path, callback)]请求服务器删除指定资源。
      PATCH:[app.patch(path, callback)]IETF RFC 5789新增的HTTP方法,功能定义是部分更新某个资源
      TRACE:[app.trace(path, callback)]回显服务器收到的请求,主要用于测试或诊断。
      CONNECT:[app.connect(path, callback)]HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。
      OPTIONS:[app.options(path, callback)]返回服务器支持的HTTP请求方法
      所有方法:[app.all(path, callback)]
     #幂等-重复请求多次与一次请求的效果是一样
    ---------------------------------
    启用页面布局功能:
     var partials = require('express-partials')
      app.configure中添加以下内容:
        app.use(partials());
      启用其它布局模板:
        #页面模板时套用admin.ejs作为页面布局
        function(req, res){res.render('userlist',{title: '用户列表后台管理系统',layout: 'admin'});};
    ---------------------------------
    片段视图:
     partials:重复的内容,用于迭代显示,将相对独立的页面块分割出去,而且可以避免显式地使用循环迭代
       app.get('/list',function(req,res){res.render('list',{title:'List',items:[2012,'Eric','express','Node.js']});});
       list.ejs:<ul><%- partial('listitem', items) %></ul>
       listitem.ejs:<li><%= listitem %></li>
    ---------------------------------
    视图助手:
      #express3.0中locals代替dynamicHelpers():
        app.use(function(req,res,next){
          var err = req.flash('error'),success = req.flash('success');
          res.locals.user = req.session.user;
          res.locals.error = err.length ? err : null;
          res.locals.success = success.length ? success : null;
          next();
        });
      允许在视图中访问一个全局的函数或对象,不用每次调用视图解析的时候单独传入
      静态视图助手:任何类型的对象,包括接受任意参数的函数,但访问到的对象必须与用户请求无关,通过app.helpers()函数注册
      动态视图助手:只能是一个函数,该函数不能接受参数,但可以访问req和res对象,通过app.dynamicHelpers()注册
      var util = require('util');
      app.helpers({
       inspect: function(obj) {
        return util.inspect(obj, true);
       }
      });
      app.dynamicHelpers({
       headers: function(req, res) {
        return req.headers;
       }
      });
      app.get('/helper', function(req, res) {
       res.render('helper', {
        title: 'Helpers'
       });
      });
     #视图中调用:
      <%=inspect(headers)%>
    ---------------------------------
    安装MongoDB:
     工程目录中package.json->dependencies中添加一行代码:
      ,"mongodb": "*" #*会默认获取最新版本
     然后运行cd microblog && npm install更新依赖的模块,接下来在工程的目录中创建settings.js文件用于保存数据库的连接信息:
        module.exports = {
          cookieSecret: 'microblog',
          db: 'microblog',
          host: 'localhost',
        };
     在工程目录下新建models目录并创建db.js:
        var settings = require('../settings');
        var Db = require('mongodb').Db;
        var Connection = require('mongodb').Connection;
        var Server = require('mongodb').Server;
        module.exports = new Db(settings.db, new Server(settings.host, Connection.DEFAULT_PORT, {}));
    ---------------------------------
    会话支持:
     工程目录中package.json->dependencies中添加一行代码:
      "connect-mongo": ">= 0.1.7"
     然后运行cd microblog && npm install更新依赖的模块,接下来在app.js中添加:
      var MongoStore = require('connect-mongo');
      var settings = require('./settings');
      app.configure(function(){
        app.set('views', __dirname + '/views');
        app.set('view engine', 'ejs');
        app.use(express.bodyParser());
        app.use(express.methodOverride());
        app.use(express.cookieParser());
        app.use(express.session({
         secret: settings.cookieSecret,
         store: new MongoStore({
          db: settings.db
         })
        }));
        app.use(app.router);
        app.use(express.static(__dirname + '/public'));
      });

    ---------------------------------
    模块的类型:
      Node.js的模块可以分为两大类,一类是核心模块,另一类是文件模块
      核心模块拥有最高的加载优先级,换言之如果有模块与其命名冲突,Node.js总是会加载核心模块
      在不显式指定文件模块扩展名的时候,Node.js会分别试图加上.js(javascript) > .json(json) > .node(c/c++)扩展名
      核心模块:
        Node.js标准API中提供的模块,如fs、http、net、vm等
    ---------------------------------
    按路径加载模块:
      相对路径:require参数以“./”或“../”开头
      绝对路径:require('/home/ms') 将会按照优先级依次尝试加载/home/ms.js、/home/ms.json、/home/ms.node
    在node_modules中加载模块:
      如果require参数不以“/”、“./”或“../”开头,而该模块又不是核心模块,那么就要通过查找node_modules加载模块
      如果没有找到,则会在当前目录的上一层中的node_modules目录中继续查找,反复执行这一过程,直到遇到根目录为止
        require('ms.js'):/home/work/node_modules/ms.js > /home/node_modules/ms.js > /node_modules/ms.js
    ---------------------------------
    加载缓存:
      Node.js模块不会被重复加载,这是因为Node.js是通过实际文件名缓存所有加载过的文件模块,而不是通过require()提供的参数缓存的
    ---------------------------------
    加载顺序:
      require(some_module)的加载顺序:
        如果some_module是一个核心模块,直接加载,结束
        如果some_module以“/”、“./”或“../”开头,按路径加载some_module,结束。
        假设当前目录为current_dir,按路径加载current_dir/node_modules/some_module
          如果加载成功,结束
          如果加载失败,令current_dir为其父目录
          重复这一过程,直到遇到根目录,抛出异常,结束
    ---------------------------------
    循环的陷阱:闭包
    ---------------------------------
    深层的回调函数嵌套:改变设计模式,时刻注意降低逻辑之间的耦合关系
    ---------------------------------
    应用部署:
      日志功能:
        Express支持两种运行模式:开发模式和产品模式,前者的目的是利于调试,后者则是利于部署
        使用产品模式运行服务器的方式很简单,命令行输入:NODE_ENV=production node app.js
        app.js:
          var fs = require('fs');
          var accessLogfile = fs.createWriteStream('access.log', {flags: 'a'});
          var errorLogfile = fs.createWriteStream('error.log', {flags: 'a'});
        app.configure函数第一行加入:
          app.use(express.logger({stream: accessLogfile}));
        错误日志-需要在产品模式中实现错误响应:
          app.configure('production', function(){
            app.use(function(err, req, res, next){
              var meta = '[' + new Date() + '] ' + req.url + '\n';
              errorLogfile.write(meta + err.stack + '\n');
              next();
            });
          });
    ---------------------------------
    多核提高性能及故障恢复:
      Node.js的核心模块child_process:生成与当前进程相同的子进程
      cluster的功能是生成与当前进程相同的子进程,并且允许父进程和子进程之间共享端口
      区别在于cluster允许跨进程端口复用
      为了外部模块能调用app.js,需要禁止服务器自动启动。修改app.js:
        var app = express() --> var app = module.exports = express()
        if (!module.parent) {//判断当前模块是不是由其他模块调用的
            http.createServer(app).listen(3000, function(){
                console.log("Express server listening on port %d in %s mode", 3000, app.settings.env);
            });
        }
      cluster.js的功能是创建与CPU核心个数相同的服务器进程,以确保充分利用多核CPU的资源。通过cluster调用app.js。创建cluster.js:
        var cluster = require('cluster');
        var os = require('os');
        // 获取 CPU 的数量
        var numCPUs = os.cpus().length;
        var workers = {};
        if (cluster.isMaster) {
          // 主进程分支
          cluster.on('death', function (worker) {
            // 当一个工作线程结束时,重新启动一个工作线程
            delete workers[worker.pid];
            worker = cluster.fork();
            workers[worker.pid] = worker;
          });
          // 初始化 CPU 数量相同的工作进程
          for (var i = 0; i < numCPUs; i++) {
            var worker = cluster.fork();
            workers[worker.pid] = worker;
          }
        } else {
          // 工作進进程分支,启动服务器
          var app = require('./app');
          app.listen(3000);
        }
        // 当主进程终止时,关闭所有工作进程
        process.on('SIGTERM', function () {
          for (var pid in workers) {
            process.kill(pid);
          }
          process.exit(0);
        });
    ---------------------------------
    启动脚本:通过nohup启动服务器,使进程不会因为退出终端而关闭
      #! /bin/sh
      NODE_ENV=production
      DAEMON="node cluster.js"
      NAME=Microblog
      DESC=Microblog
      PIDFILE="/usr/works/microblog.pid"
      case "$1" in
        start)
            echo "Starting $DESC: "
            nohup $DAEMON > /usr/works/microblog &
            echo $! > $PIDFILE
            echo "$NAME."
            ;;
        stop)
            echo "Stopping $DESC: "
            pid=`cat $PIDFILE`
            kill $pid
            rm $PIDFILE
            echo "$NAME."
            ;;
        esac
        exit 0
    ---------------------------------
    反向代理:
      Nginx:
        server {
          listen 80;
          server_name microblog.com;
          location / {
            proxy_pass http://localhost:3000;
          }
        }
    ---------------------------------
    Nginx配置文件中添加访问静态文件的规则
      删除app.js中的app.use(express.static(path.join(__dirname, 'public')));

  • 相关阅读:
    Anaconda + Djongo + spyder 网站开发 (三)
    Anaconda + Djongo + spyder 网站开发 (二)
    Anaconda + Djongo + spyder 网站开发 (一)
    实验室网盘链接方式
    R 缓存画图代码,之后再总结
    换源的重要性!!!!
    latex 调整页边距
    Latex 字体设置
    嵌套交叉验证
    FDR及Benjamini-Hochberg方法
  • 原文地址:https://www.cnblogs.com/wen12128/p/2832584.html
Copyright © 2020-2023  润新知