nodejs debug 设定程序执行起始根路径cwd

launch.json

{
    // 使用 IntelliSense 了解相关属性。 
    // 悬停以查看现有属性的描述。
    // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "type": "pwa-node",
            "request": "launch",
            "name": "Launch Program",
            "skipFiles": [
                "<node_internals>/**"
            ],
            "program": "${workspaceFolder}\\cus_jd_scripts\\js\\jd_cash.js",
            "cwd": "${workspaceFolder}\\cus_jd_scripts\\js\\",
        }
    ]
}

  1. 截止目前最新win11版本号(21h2 22000.527)
  2. 浏览器打开https://store.rg-adguard.net
    下拉框和文本框分别选择和输入——ProductID,9P3395VX91N,Slow;最后点击“√”查询按钮


    或者云盘下载: https://pan.baidu.com/s/19YD4MxGGJkSEhGaU_SELPQ?pwd=wn24 提取码: wn24

  3. 查询结果中
    下载最后一个名为“MicrosoftCorporationII.WindowsSubsystemForAndroid_1.8.32837.0_neutral_~_8wekyb3d8bbwe.msixbundle”的文件

  4. 安装WSA
    D盘根目录下创建目录“D:\WSA”,并将上面下载的文件copy到本目录下,然后管理员身份运行windows程序“PowerShell”,最后执行进入目录和安装命令

    d:
    cd D:\WSA
    Add-AppxPackage MicrosoftCorporationII.WindowsSubsystemForAndroid_1.8.32837.0_neutral___8wekyb3d8bbwe.Msixbundle

  5. 启动WSA,并开启开发者模式,从而允许安装非Amazon Appstore的应用,(同时记住wsa服务的IP地址)
  6. windows下安装adb工具,或者通过windows store应用商店安装-“Apk文件安装程序”
  7. 通过adb命令给windows安卓子系统,安装自定义的安卓app应用,比如douyin,cmd执行以下命令:
    cd 相应文件目录
    # adb连接was服务
    adb connect 172.22.137.166
    # adb安装自定义应用到安卓子系统
    adb install aweme_douyin-huidu-gw-huidu-220209_v1019_190500_4c20_1644405940.apk

  8. 启动Android应用。
    点击“开始”按钮——点击所有应用——点击刚刚安装抖音apk-启动(大功告成)


  9. 卸载和删除Android应用
    开始按钮-所有应用-右键刚刚安装的Android应用——选择卸载

作用

  1. 后端提供restful api接口
  2. 前端提供页面展示


而前端日常开发时,大致有以下几种开发模式(vue2.0版本)

  1. 使用npm run dev模式,且通过配置proxyTable,将axios的前端请求转发给实际的后端地址(常用


    1. 项目根下的config目录


      • index.js

      'use strict'
      // Template version: 1.3.1
      // see http://vuejs-templates.github.io/webpack for documentation.
      
      const path = require('path')
      
      module.exports = {
        dev: {
          // Paths
          assetsSubDirectory: 'static',
          assetsPublicPath: '/',
          proxyTable: {
            '/api': {
              target: 'http://127.0.0.1:8080', // 后端接口地址
              changeOrigin: true, // 是否允许跨域
              pathRewrite: {
                '^/api': '' // 重写
              }
            }
          },
      
          // Various Dev Server settings
          host: 'localhost', // can be overwritten by process.env.HOST
          port: 80, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
          autoOpenBrowser: true,
          errorOverlay: true,
          notifyOnErrors: true,
          poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
      
          // Use Eslint Loader?
          // If true, your code will be linted during bundling and
          // linting errors and warnings will be shown in the console.
          useEslint: true,
          // If true, eslint errors and warnings will also be shown in the error overlay
          // in the browser.
          showEslintErrorsInOverlay: false,
      
          /**
           * Source Maps
           */
      
          // https://webpack.js.org/configuration/devtool/#development
          devtool: 'cheap-module-eval-source-map',
      
          // If you have problems debugging vue-files in devtools,
          // set this to false - it *may* help
          // https://vue-loader.vuejs.org/en/options.html#cachebusting
          cacheBusting: true,
      
          cssSourceMap: true
        },
      
        build: {
          // Template for index.html
          index: path.resolve(__dirname, '../dist/index.html'),
      
          // Paths
          assetsRoot: path.resolve(__dirname, '../dist'),
          assetsSubDirectory: 'static',
          assetsPublicPath: '/',
      
          /**
           * Source Maps
           */
      
          productionSourceMap: false,
          // https://webpack.js.org/configuration/devtool/#production
          devtool: '#source-map',
      
          // Gzip off by default as many popular static hosts such as
          // Surge or Netlify already gzip all static assets for you.
          // Before setting to true, make sure to:
          // npm install --save-dev compression-webpack-plugin
          productionGzip: true,
          productionGzipExtensions: ['js', 'css'],
      
          // Run the build command with an extra argument to
          // View the bundle analyzer report after build finishes:
          // npm run build --report
          // Set to true or false to always turn it on or off
          bundleAnalyzerReport: process.env.npm_config_report
        }
      }
      

      • dev.env.js

      'use strict'
      const merge = require('webpack-merge')
      const prodEnv = require('./prod.env')
      
      module.exports = merge(prodEnv, {
        NODE_ENV: '"development"',
        BASE_API: '"/api"'
      })
      

      • prod.env.js

      'use strict'
      module.exports = {
        NODE_ENV: '"production"',
        // BASE_API: '"http://georege.slhk.com/"'
      }
      
    2. 项目根下的src目录下自己封装api目录


      • axios-filter.js

      import axios from 'axios'
      import { Message } from 'element-ui'
      import router from '@/router'
      
      // 根据不同环境自动读取不同的baseurl
      if (process.env.NODE_ENV === 'development') {
        axios.defaults.baseURL = process.env.BASE_API
      }
      // 读取cookie中的csrftoken
      axios.defaults.xsrfCookieName = 'csrftoken'
      // axios header设置X-CSRFTOKEN
      axios.defaults.xsrfHeaderName = 'X-CSRFTOKEN'
      // 设置Content-Type
      axios.defaults.headers = {
        'Content-Type': 'application/json;charset=UTF-8'
      }
      // 设置超时时间
      axios.defaults.timeout = 50000
      
      // request拦截器
      axios.interceptors.request.use(
        config => {
          // sessionStorage 如果存在jwt token
          if (sessionStorage.token) {
            // 则JWT token认证格式,写入header
            config.headers.Authorization = 'JWt ' + sessionStorage.token
            // console.log(sessionStorage.token)
          }
          return config
        },
        error => {
          // console.log(error)
          return Promise.reject(error)
        }
      )
      // reponse自定义拦截器 start
      function customAxiosResponseInterceptor () {
        const interceptor = axios.interceptors.response.use(
          response => response,
          error => {
            // console.log(error)
            var config = error.config
            if (error.response.status === 401) {
              axios.interceptors.response.eject(interceptor)
              const v = sessionStorage.getItem('refresh')
      
              if (typeof v === 'undefined' || v === null || v === '') {
                Message({
                  showClose: true,
                  message: error.response.data.msg,
                  type: 'error'
                })
              } else {
                let data = { 'refresh': v }
                return axios.post('/api-token-refresh/', data).then(response => {
                  sessionStorage.setItem('token', response.data.access)
                  console.log('刷新 access token 成功')
                  // 重新发送请求
                  return axios(config)
                }).catch(error => {
                  Message({
                    showClose: true,
                    message: '登录超时,请重新登录!!!',
                    type: 'error'
                  })
                  redirectLoginWithQuery()
                  console.log(error)
                  return Promise.reject(error)
                }).finally(customAxiosResponseInterceptor)
              }
            } else {
              console.log(error.response)
              // Message({
              //   showClose: true,
              //   message: error.response.data.msg,
              //   type: 'error'
              // })
              return Promise.reject(error)
            }
          }
        )
      }
      customAxiosResponseInterceptor()
      // reponse自定义拦截器 end
      // login with redirect
      function redirectLoginWithQuery () {
        router.push({
          path: '/login',
          query: {
            redirect: router.currentRoute.fullPath
          }
        })
      }
      export default axios
      
    3. 项目目录结构

  2. 使用npm run build模式,直接dist下打包编译出生产所需静态文件

  3. 使用npm run watch模式(需要安装watch组件,且需要配置package.json文件中的scripts的内容)


    • package.json

      "scripts": {
          "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
          "start": "npm run dev",
          "lint": "eslint --ext .js,.vue src",
          "build": "node build/build.js",
          "watch": "nodemon --watch src -e html,vue,js,less build/build.js"
        },

设备登陆setting sync,ctrl+shift+p,选择Sync:下载配置,提示安装插件失败

打开帮助——切换开发人员工具,会看到相关错误输出,找不到某个名称的插件(可能该插件存在风险等原因被插件市场下架了)

解决办法:

  1. 打开自己绑定的gist地址如:https://gist.github.com/git空间名称
  2. 然后点击“git空间名称 / cloudSettings Secret”
  3. 然后点击edit
  4. 选择extensions.json文件,然后删除里面已经被插件市场下架的插件内容
  5. ctrl+shift+p,重新选择Sync:下载配置即可。