笔记 vue 项目中 配置开发、正式环境变量使用nginx 解决跨域

471 阅读3分钟
  1. 配置全局 NODE_ENV 变量 方便后面封装 api 请求时根据变量的变化切换请求路径
  2. 由于浏览器不能直接访问服务器 但是 服务器和服务器没有这个限制 所以可以通过安装nginx转发我们要请求的地址,设置好nginx 服务名,项目访问nginx,再由nginx请求真正的后台地址
  • package.json 文件先配置 开发环境和正式环境 的全局变量, 开发环境运行 npm run dev 时 NODE_ENV=development,正式环境运行 npm run build打包时 NODE_ENV=production 记得要安装cross-env呦
  "scripts": {
    "dev": "cross-env NODE_ENV=development vue-cli-service serve",
    "test": "cross-env NODE_ENV=testing vue-cli-service build",
    "build": "cross-env NODE_ENV=production vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  • 现在通过process.env.NODE_ENV 获取刚才配置的全局变量 来控制不同环境的请求地址 process.env.NODE_ENV === 'development' 是本地开发环境,process.env.NODE_ENV === 'production' 线上正式环境。
import axios from 'axios/dist/axios.min';

var qs = require('qs');
import {Message} from 'ant-design-vue'

let base = '',
    upPath = '',
    domain = '',
    webDomain = '';
if (process.env.NODE_ENV === 'development') {
  //本地开发环境
  base = 'http://dev.renhe-crm.yinhedw.com/privateapi';
  upPath = '/privateapi';
  domain = 'http://dev.renhe-crm.yinhedw.com';
} else if (process.env.NODE_ENV === 'production') {  
  //线上正式环境
  base = 'http://renhe-crm.yinhedw.com';
  domain = 'http://renhe-crm.yinhedw.com';
  upPath = '';
}
/**=====================================================================================
 * 公共方法
 *======================================================================================*/
export default {
  COMMON: {
    BASE: base,
    UPLOADPATH: upPath,
    DOMAIN: domain,
    WEBDOMAIN: webDomain,
    /**
     * [description] message 持续时间
     * @type {Number}
     */
    DURATION: 4000,
    /**
     * [description] 判断是否具有访问 id 模块的权限
     * @param  {[type]} id [description]
     * @return {[type]}    [description]
     */
    getPermissionStatus: (id) => {
      let ids = localStorage.getItem('userType') || "";
      if (ids == id) {
        return true;
      }
      return false;
    },
    /**
     * [description] 毫秒数转成需要的格式
     * @param  {[type]} type      [description] 1: yyyy-mm-dd. 2: yyyy-mm-dd hh:mm:ss
     * @param  {[type]} separator [description] 分隔符
     * @param  {[type]} time      [description] 毫秒数
     * @return {[type]}           [description]
     */
    formatDate: (type, separator, time) => {
      let formatdate = new Date(time),
          year = formatdate.getFullYear(),
          month = formatdate.getMonth(),
          day = formatdate.getDate(),
          hours = formatdate.getHours(),
          minute = formatdate.getMinutes(),
          second = formatdate.getSeconds();


      month = (month + 1) < 10 ? ('0' + (month + 1)) : (month + 1);
      day = day < 10 ? ('0' + day) : day;
      hours = hours < 10 ? ('0' + hours) : hours;
      minute = minute < 10 ? ('0' + minute) : minute;
      second = second < 10 ? ('0' + second) : second;

      if (type == 1) {
        return year + separator + month + separator + day;
      } else if (type == 2) {
        return year + separator + month + separator + day + ' ' + hours + ':' + minute + ':' + second;
      } else {
        return time;
      }
    },
    /**
     * [getNowWeek description] 获取本周
     * @return {[type]} [description]
     */
    getNowWeek: function () {
      let now = new Date(),
          dayOfWeek = now.getDay();

      if (dayOfWeek == 0) {
        dayOfWeek = 6;
      } else {
        dayOfWeek -= 1;
      }

      return [COMMON.formatDate(1, '-', now.getTime() - dayOfWeek * 24 * 3600 * 1000), COMMON.formatDate(1, '-', now.getTime())]
    },
    /**
     * [getNowMonth description] 获取本月
     * @return {[type]} [description]
     */
    getNowMonth: function () {
      let now = new Date(),
          month = now.getMonth(),
          year = now.getFullYear();

      return [COMMON.formatDate(1, '-', new Date(year, month, 1)), COMMON.formatDate(1, '-', now.getTime())]
    },
    /**
     * [getMonthDays description] 获取某月份的天数
     * @param  {[type]} myMonth [description]
     * @return {[type]}         [description]
     */
    getMonthDays(month) {
      let now = new Date(),
          year = now.getFullYear();

      let startDate = new Date(year, month, 1),
          endDate = new Date(year, month + 1, 1);

      return (endDate - startDate) / (1000 * 60 * 60 * 24);
    },
    /**
     * [formatterDateRange description] 获取起始日期的0点毫秒数、结束日期的24点毫秒数
     * @param  {[type]} dateStart [description]
     * @param  {[type]} dateEnd   [description]
     * @return {[type]}           [description]
     */
    formatterDateRange: function (dateStart, dateEnd) {
      let startDateTime = new Date(new Date(dateStart).toLocaleDateString()).getTime(),
          endDateTime = new Date(new Date(dateEnd).toLocaleDateString()).getTime() + 24 * 60 * 60 * 1000 - 1;

      return [startDateTime, endDateTime];
    },
    /**
     * [setCookie description] 设置cookie
     * @param {[type]} cname  [description]
     * @param {[type]} cvalue [description]
     * @param {[type]} exdays [description]
     */
    setCookie: function (cname, cvalue, exdays) {
      var d = new Date();
      d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
      var expires = "expires=" + d.toUTCString();
      document.cookie = cname + "=" + cvalue + "; " + expires;
    },
    /**
     * [getCookie description] 获取cookie
     * @param  {[type]} name [description]
     * @return {[type]}      [description]
     */
    getCookie: function (name) {
      var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");

      if (arr = document.cookie.match(reg))

        return (arr[2]);
      else
        return null;
    },
    /**
     * [delCookie description] 删除cookie
     * @param  {[type]} name [description]
     * @return {[type]}      [description]
     */
    delCookie: function (name) {
      var exp = new Date();
      exp.setTime(exp.getTime() - 1);
      var cval = COMMON.getCookie(name);
      if (cval != null) {
        document.cookie = name + "=;expires=" + exp.toGMTString() + ";domain=" + cookieDomain + ";path=/";
      }
    },
    /**
     * [api description]
     * @param  {string} url         [description] 接口地址
     * @param  {object} params      [description] 接口参数
     * @param  {string} method      [description] 方式
     * @return {promise}             [description]
     */
    api: function (url, params, method, contentType) {
      let lang = localStorage.getItem('lang') == 'zh' ? 'zh_cn' : 'en_us';

      if (method == 'get') {
        return axios.get(`${base}${url}`, {'params': params}, {
          headers: {
            'apiMethod': 'ajax',
            'content-type': 'application/x-www-form-urlencoded',
            lang: lang
          }
        }).then(res => res.data);
      } else {
        if (contentType == 'formData') {
          return axios.post(`${base}${url}`, params, {
            headers: {
              'apiMethod': 'ajax',
              'content-type': 'multipart/form-data',
              lang: lang
            }
          }).then(res => res.data);
        } else if (contentType == 'form') {
          return axios.post(`${base}${url}`, qs.stringify(params), {
            headers: {
              'apiMethod': 'ajax',
              'content-type': 'application/x-www-form-urlencoded',
              lang: lang
            }
          }).then(res => res.data);
        } else if (contentType == 'file') {
          return axios.post(`${base}${url}`, params, {
            responseType: 'arraybuffer',
            headers: {'apiMethod': 'ajax', 'content-type': 'application/json;charset=UTF-8', lang: lang}
          }).then(res => res.data);
        } else {
          return axios.post(`${base}${url}`, params, {
            headers: {
              'apiMethod': 'ajax',
              'content-type': 'application/json;charset=UTF-8',
              lang: lang
            }
          }).then(res => res.data);
        }
      }
    },
    /**
     * [dowloadImg 下载图片]
     * @param {string} url 要下载的图片地址
     * @param {any} name 图片名称
     * */
    dowloadImg(url, name) {
      let image = new Image()
      image.setAttribute('crossOrigin', 'anonymous')
      image.src = url
      image.onload = () => {
        let canvas = document.createElement('canvas')
        canvas.width = image.width
        canvas.height = image.height
        let ctx = canvas.getContext('2d')
        ctx.drawImage(image, 0, 0, image.width, image.height)
        canvas.toBlob((blob) => {
          let url = URL.createObjectURL(blob)
          let eleLink = document.createElement('a')
          eleLink.download = name
          eleLink.href = url
          eleLink.click()
          eleLink.remove()
          // 用完释放URL对象
          URL.revokeObjectURL(url)
        })
      }
    },
    /**
     * [downsFile 下载文件]
     * @param {string} url 要下载的文件地址
     * @param {any} name 文件名称
     * */
    downsFile(url) {
      window.location.href = "/crm/file/download?url=" + url;
    }
  }
}
  • vue.config.js 文件通过devServer配置端口 要和 nginx 中proxy_pass配置项的端口对应 此项目 配置 8836
module.exports = {
    publicPath: '',
    outputDir: 'dist',  //打包路径
    assetsDir: 'static',  //静态资源存放路径,相对于outputDir

    lintOnSave: false,  //开发环境开启eslint检查
    =======配置端口==========
    devServer: {
        port: 8836, // 端口号
        disableHostCheck: true  //跳过webpack-dev-server的hostname安全验证
    }
}
  • 配置nginx解决本地访问服务端跨域 ,此服务配置为dev.renhe-h5.yinhedw.com ,hosts文件对应 ip 配置为 127.0.0.1 dev.renhe-h5.yinhedw.com ,不要忘记设置 host呦

打开nginx.conf配置,下面为此项目配置

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    server_names_hash_bucket_size 64;

    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }

    server {
        listen          80;
        # 项目中要访问的地址
        server_name     dev.renhe-crm.yinhedw.com; 
        client_max_body_size 1024M;
        location = / {
                rewrite ^/$ /index last;
        }

        location / {
                try_files $uri $uri/ /index.html;
        }
        
        # 匹配到静态文件转发到 http://127.0.0.1:8836
        location ~ .*\.(zip|gif|jpg|jpeg|png|bmp|swf|js|css|html|woff|tff|woff2|ttf)$ { 
                proxy_pass      http://127.0.0.1:8836;
                proxy_set_header        Host    $host;
                proxy_set_header        X-Real-IP   $remote_addr;
                proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        }
        # 匹配到接口含有privateapi字段的转发到 http://renhe-crm.yinhedw.com/
        # http://renhe-crm.yinhedw.com/ 真正要请求的后台地址
        # 例如http://dev.renhe-crm.yinhedw.com/privateapi/abcd 经过转发后就变成 http://renhe-crm.yinhedw.com/privateapi/abcd 
        location ^~/privateapi/ {
                proxy_pass      http://renhe-crm.yinhedw.com/;
        }

        location ~ {
                proxy_pass      http://127.0.0.1:8836;
                proxy_set_header        Host    $host;
                proxy_set_header        X-Real-IP   $remote_addr;
                proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;            
        }
    }

 

    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}
  • host文件配置 host.png