13、gulp、webpack、三大框架之登录|权限|路由嵌套|状态管理|请求响应拦截、angular1项目下index.html的注入与执行、安装服务器系统、操作服务器系统、Linux|ubuntu|VMware、electron、服务端渲染、__dirname|join|resolve、npm|cnpm|yarn|tyarn|bootstrap


一、gulp
1、gulp的API
(1)gulp.src(globs[, options])导入文件的路径
(A)globs参数匹配文件路径(路径包括文件名,分为具体路径和通配符路径)。当有多个路径时,该参数为一个数组。
(B)options为可选参数。通常情况下我们不需要用到。
(C)* 匹配文件路径中的0个或多个字符,但不会匹配路径分隔符,除非路径分隔符出现在末尾
(D)** 匹配路径中的0个或多个目录及其子目录,需要单独出现,即它左右不能有其他东西了。如果出现在末尾,也能匹配文件。
(D)gulp.src(['js/*.js','css/*.css','*.html'])
(E)使用数组的方式还有一个好处就是可以很方便的使用排除模式,在数组中的单个匹配模式前加上!即是排除模式,它会在匹配的结果中排除这个匹配,要注意一点的是不能在数组中的第一个元素中使用排除模式
(F)gulp.src([*.js,'!b*.js']) //匹配所有js文件,但排除掉以b开头的js文件
(G)gulp.src(['!b*.js',*.js]) //不会排除任何文件,因为排除模式不能出现在数组的第一个元素中2)gulp.dest(path[,options])导出文件的目录
(A)path为写入文件的路径
(B)options为一个可选的参数对象,通常我们不需要用到
(C)gulp.dest()传入的路径参数,只能用来指定要生成的文件的目录,生成的文件名是由导入到它的文件流决定的。
(D)gulp.dest(path)生成的文件路径是我们传入的path参数后面再加上gulp.src()中有通配符开始出现的那部分路径。例如:
(D)gulp.src('script/**/*.js') .pipe(gulp.dest('dist')); //最后生成的文件路径为 dist/**/*.js3)gulp.task(name[, deps], fn)用来定义任务
(A)name 为任务名
(B)deps 是当前定义的任务需要依赖的其他任务,为一个数组。当前定义的任务会在所有依赖的任务执行完毕后才开始执行。
(C)fn 为任务函数,我们把任务要执行的代码都写在里面。
(D)gulp.task('mytask', ['array', 'of', 'task', 'names'], function() { //定义一个有依赖的任务 // Do something});
(D)gulp中执行多个任务,可以通过任务依赖来实现。例如我想要执行one,two,three这三个任务,那我们就可以定义一个空的任务,然后把那三个任务当做这个空的任务的依赖就行了:
 //只要执行default任务,就相当于把one,two,three这三个任务执行了
(E)gulp.task('default',['one','two','three']);
(F)如果任务相互之间没有依赖,任务会按你书写的顺序来执行,如果有依赖的话则会先执行依赖的任务。
(G)但是如果某个任务所依赖的任务是异步的,就要注意了,gulp并不会等待那个所依赖的异步任务完成,而是会接着执行后续的任务。
(4)gulp.watch(globs[, opts], tasks)或gulp.watch(glob[, opts, cb])用来监视文件的变化,当文件发生变化后,我们可以利用它来执行相应的任务
(A)globs参数匹配文件路径(路径包括文件名,分为具体路径和通配符路径)。当有多个路径时,该参数为一个数组。
(B)opts 为一个可选的配置对象,通常不需要用到
(C)tasks 为文件变化后要执行的任务,为一个数组
(D)cb参数为一个函数。每当监视的文件发生变化时,就会调用这个函数,并且会给它传入一个对象,该对象包含了文件变化的一些信息,type属性为变化的类型,可以是added,changed,deleted;path属性为发生变化的文件的路径
(E)gulp.watch('js/**/*.js', function(event){
     console.log(event.type); //变化类型 added为新增,deleted为删除,changed为改变
     console.log(event.path); //变化的文件的路径
 });
2、gulp介绍
(1)gulp自动化工具的作用:
(A)打包,供生产环境使用。
(B)监听,供开发环境使用。
(2)gulp自动化工具的数据来源:
(A)请求静态资源时,通过配置指向本机;
(B)请求动态数据时,通过配置指向服务器。
(C)生产环境下,所有的数据都按照代码里面的url获取
3、在gulp下,建立karma任务
来源:https://www.cnblogs.com/2050/p/4198792.html
var karma = require('karma').server;
gulp.task('test', function(done) {
  karma.start({
    configFile: __dirname + '/tests/my.conf.js',
    singleRun: true
  }, function() {
    done();
  });
});
4、gulpfile.js
var fs = require('fs');
var url = require('url');
var gulp = require('gulp');
var Gaze = require('gaze').Gaze;
var browserSync = require('browser-sync').create();
var reload = browserSync.reload;
var proxy = require('proxy-middleware');
var getGulpPlugin = require('gulp-load-plugins')();
var runSequence = require('run-sequence');
5、gulp开发流程
gulp.task('default', function () {
  testServe('cy', 'cy');
});
function testServe(moduleDirName, configDirname) {
  //(1)向index.html里注入js(含被压缩成js的html)、css
  injectAndReload(moduleDirName, configDirname);
  //(2)监听各路径下文件的增减和文件内容的改变
  gaze && gaze.close();
  browserSync && browserSync.exit();
  gaze = new Gaze('src/**/*');
  gaze.on('all', function () {
    injectAndReload(moduleDirName, configDirname);
  });
  //(3)代理请求并重新加载index.html
  var myProxy = [
    '/app',
    '/global',
    '/logio',
  ].map(function (value) {
    var a = url.parse('http://192.168.80.152:7300'+value);
    a.route = value;
    return proxy(a);
  });
  browserSync.init({
      port: 8900,
      notify: false,
      open: false,
      server: {
        baseDir: ['src'],//开发过程中,需要的所有文件都应该放在src文件夹下,尤其是某状态的html文件
        directory: false,
        index: 'index.html',
        middleware: myProxy,
        routes: {
          '/audit-html/static/img': 'src/img',//服务器存放文件的路径:本地开发时存放文件的路径
          '/config/project/static/img': 'src/img'
        }
      }
    },
    function () { reload(); }
  );
}
function injectAndReload(moduleDirName, configDirname) {
  var jsArray = getJsCssHtml(configDirname).js;
  var cssArray = getJsCssHtml(configDirname).css;
  var htmlArray = getJsCssHtml(configDirname).tpl;
  gulp.src(htmlArray)
    .pipe($.htmlmin({collapseWhitespace: true,removeComments: true,minifyCSS: true}))//将html连同它所在的文件夹一起抽出,并进行最基本的压缩(去空格、去注释)
    .pipe($.angularTemplatecache({module: 'app'}))//将各文件夹里的HTML按照路径合并到一个js文件里,并缓存到app模块里
    .pipe(gulp.dest('template'));//导出js文件,下面与其它js拼接时,放在最后
  var array = jsArray.concat(cssArray,['template/htmlJS.js']);
  gulp.src('src/tpl/index.html')
    .pipe($.inject(gulp.src(array), {relative: true}))//注入区域为<!-- inject:js --> <!-- endinject -->
    .pipe(gulp.dest('src/'))
    .on('end', reload);
}
6、gulp打包流程
// 引进的类库只打包不压缩,自己写的文件既打包又压缩。
// 打包后的文件,在开发时都存放在文件夹dist下,
// 在生产时都放在文件夹/audit-html/static/下;
// 生产页面index.html在生产时,放在audit-html/template下
gulp.task('build', function () {
  gulp.src(['tmp', 'dist', 'rev']).pipe(clean());//清除文件夹内容,为本次打包腾地方
  gulp.src(paths).pipe(gulp.dest('dist/img'));//导出图片,供页面加载时使用
  gulp.src(['src/vendor/common-vendor/**'])
    .pipe(gulp.dest('dist/common'));//导出类库,供生产页面index.html的<link href="">和<script src=""></script>引用
  gulp.src(['src/brows/*']).pipe(gulp.dest('dist/brows'));//导出浏览器,供交互时返回
  gulp.src(['src/index.html'])//打包index.html里<!-- build:js scripts/all.min.js --><!-- endbuild -->之间的资源
    .pipe($.useref())//将html进行合并。
    .pipe($.if('*.js', $.ngAnnotate()))//解决angular中,依赖注入出错的问题
    .pipe($.if('*.js', $.uglify()))//压缩js
    .pipe($.if('*.css', $.cleanCss()))//压缩css
    .pipe(gulp.dest('dist'));//导出文件为'dist/scripts/all.min.js',由注释标签里的内容决定
  gulp.src(['./dist/style/all.min.css', './dist/script/all.min.js'])//添加hash后缀,避免新旧文件混淆
    .pipe(rev())//添加hash后缀
    .pipe(gulp.dest('./dist'))//导出文件为'dist/styles/all_34543.min.css'和'dist/styles/all_abcba.min.css',供生产页面index.html的<link href="">和<script src=""></script>引用
  gulp.src(['dist/scripts/all.min.js','dist/styles/all.min.css','dist/index.html'])//删除临时文件,只留将上线的文件
    .pipe(clean());//删除上面三个文件
});

二、webpack
chunk 代码块。
polyfill 兜底。在计算机中,变相实现不能直接实现的操作。
process 对象是一个 global 变量,提供有关当前 Node.js 进程的信息并对其进行控制。
npm与nodejs版本对应关系:https://nodejs.org/zh-cn/download/releases/
dll,动态链接库英文为DLL,是Dynamic Link Library的缩写。(Dynamic,[daɪˈnæmɪk],有活力的)
1、基本知识
(1)安装node环境,nodejs环境变量指的是node环境安装的地方
(2)安装webpack和webpack-cli包
(3)node是运行node文件的命令
(4)npm是node包管理器、npm run start/stop/test可以简写为npm start/stop/test
(5)npm运行的包,必须写入到package.json里面才能运行
(6)npx运行的包,可以在任何地方运行,运行时,从本目录开始逐层向上直至全局(nodejs环境变量)寻找该包,找到就运行,没有找到就临时安装并直接运行,运行结束后删掉;如果想运行层级以外的版本,则加上版本号即可,如npx webpack-dev-server@3.10.3;
(7)直接运行的包,如果本目录或全局安装了该包,可以直接运行,不需要npm和npx,如webpack、webpack-dev-server。
2、开发或生产环境
(1)webpack:是打包的命令,也是模块打包器。将entry输入的文件用module.rules编译打包后,根据mode取值不同而选择压不压缩最终的js,最后通过output把js显性输出到指定目录。
(2)webpack-cli:使webpack命令能(在命令行中)运行,cli即命令行接口(Command Line Interface)。
(3)webpack-dev-server:是开启本地node服务器的命令,也是一个小型的node服务器。将entry输入的文件用module.rules编译打包后,根据mode取值不同而选择压不压缩最终的js,最后通过output把js隐性输出到内存并自动打开浏览器,同时监听entry及其import引入的文件,一旦发生变化就自动编译、打包、隐性输出代码,手动刷新浏览器,可以看到最新效果。
(4)在(1)(3)编译的过程中,根据babel-loader的配置处理js的兼容,根据process.env.NODE_ENV取值不同,选择package.json里browserslist的不同配置项来处理css的兼容问题,根据插件配置决定最终的css压不压缩和输出目录,根据url-loader的配置决定最终的img输出目录和公共路径。
(5)以下webpack.config.js文件示例
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const webpack = require('webpack');
process.env.NODE_ENV = "development";//打包时使用package.json里browserslist里development配置来处理js/css兼容,即兼容到各浏览器的哪个版本;
module.exports = {
  entry: './src/js/index.js',//引入js,字符串和数组为单入口,对象为多入口;另外对象的value也可以是数组
  output: {
    filename: 'js/built.js',//导出js文件,如果和entry路径的深度不一样,那么webpack会自动调整图片的引用路径
    path: resolve(__dirname, 'build')
  },
  publicPath: '/',// 给所有资源引入公共路径前缀'/',如'imgs/a.jpg'==>'/imgs/a.jpg'
  mode: 'development',//用webpack打包时不压缩,取'production'则压缩
  module: {
    rules: [//loader配置
      {
        test: /\.less$/,// 处理less资源
        use: ['style-loader', 'css-loader', 'less-loader']//从右向左执行
        //'style-loader'开发环境用。在下面的js文件里,隐式地为每个样式文件创建一个style标签并将该样式放入,再将每一个style标签插到head标签里;隐式地自动将output.filename引给JavaScript标签并插入到template里的body标签里。这样head标签里不会有style标签,但控制台里有。
        //'css-loader',将css文件整合到js文件中
        //'less-loader'将less文件转换为css文件
      },
      {
        test: /\.css$/,
        use: [//从下向上执行
          MiniCssExtractPlugin.loader,//提取下面js里的css成单独文件。
          'css-loader',//将css文件整合到js文件中
          {
            loader: 'postcss-loader',//css兼容处理
            /*
              一、css兼容处理:
              1、postcss-loader(提供postcss)
              2、postcss-preset-env(帮postcss找到package.json中browserslist里面的配置,加载指定的css兼容性样式)
              3、package.json中的相关配置
              "browserslist": {
                "development": [//设置node环境变量:process.env.NODE_ENV = "development"
                  "last 1 chrome version",
                  "last 1 firefox version",
                  "last 1 safari version"
                ],
                "production": [//默认是看生产环境
                  ">0.2%",
                  "not dead",
                  "not op_mini all"
                ]
              }
            */
            options: {
              ident: 'postcss',
              plugins: () => [// postcss的插件
                require('postcss-preset-env')()
              ]
            }
          }
        ]
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: [
          {
            /*
              开启多进程打包。
              进程启动大概为600ms,进程通信也有开销。
              只有工作消耗时间比较长,才需要多进程打包
            */
            loader: 'thread-loader',
            options: {
              workers: 2 // 进程2个
            }
          },
          {
            loader: 'babel-loader',//js兼容处理
            /*
              二、js兼容处理:
              1、基本兼容处理如箭头函数,用(1)babel-loader(显性使用)(2)@babel/core(隐性支持)(3)@babel/preset-env(显性使用)
              2、复杂兼容处理如promise,除了1以外,还需要用按需加载的(4)core-js(显性使用)或全部引入的(5)@babel/polyfill(显性使用)    
              3、【babel-loader@8 requires Babel 7.x (the package '@babel/core')】
            */
            options: {
              presets: [// 预设:指示babel做怎么样的兼容性处理
                [
                  '@babel/preset-env',
                  {
                    useBuiltIns: 'usage',// 按需加载
                    corejs: {version: 3},// 指定core-js版本
                    targets: {// 指定兼容性做到哪个版本浏览器
                      chrome: '60',
                      firefox: '60',
                      ie: '9',
                      safari: '10',
                      edge: '17'
                    }
                  }
                ]  
              ],
              cacheDirectory: true//开启babel缓存,第二次构建时,会读取之前的缓存
            }
          }
        ]
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        include: resolve(__dirname, 'src'),// 只检查 src 下的js文件
        enforce: 'pre',//2个js匹配,这个优先执行。也可以像处理css文件那样,把2个包放到1个use数组里。延后执行'post'
        loader: 'eslint-loader',
        /*
          三、js语法检查:
          1、eslint-loader(显性使用) eslint(隐性支持),eslint-config-airbnb-base(隐性支持) eslint-plugin-import(隐性支持)
          2、package.json中的相关配置
          "eslintConfig": {
            "extends": "airbnb-base"
          }
          3、//eslint-disable-next-line,下一行所有eslint规则都失效
        */
        options: {
          fix: true// 自动修复eslint的错误
        }
      },
      {
        test: /\.(jpg|png|gif)$/,// 处理.css中的图片
        loader: 'url-loader',//在.css中的图片,通过css-loader存储到js文件中,在js文件里改名后,可根据图片大小将图片转码为base64保存在js中或用common.js(默认用ES6,在配置中被esModule:false关闭)模块导出。js里存储了图片改前名和改后名的关联,后来再用到这张图片时会用到这个关联。
        options: {
          limit: 8 * 1024,
          name: '[hash:10].[ext]',
          esModule: false,// 关闭es6模块化
          outputPath: "img",
          publicPath: "/img",
        }
      },
      {
        test: /\.html$/,// 处理html中的图片
        loader: 'html-loader'//在.html文件img标签中的图片,用common.js模块处理,从而能被url-loader进行处理。
      },
      {
        exclude: /\.(html|js|css|less|jpg|png|gif)/,// 处理其他资源
        loader: 'file-loader',//原封不动地输出文件
        options: {
          name: '[hash:10].[ext]',
          outputPath: 'media',
          publicPath: "/media",
        },
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/built.css'//导出css文件。默认配置为filename: './main.css'
    }),
    new OptimizeCssAssetsWebpackPlugin(),//对上面导出的css进行压缩
    new HtmlWebpackPlugin({//将导出的js文件或css文件插入到html文件head-link里或body-script里
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,//去除index.html里面的空白
        removeComments: true//去除index.html里面的注释
      }
    }),
    new webpack.NamedModulesPlugin(), // 告知哪个文件被热替换(非必需)
    new webpack.HotModuleReplacementPlugin(), // 热替换插件
    new WorkboxWebpackPlugin.GenerateSW({
      /*
        1. 帮助serviceworker快速启动
        2. 删除旧的 serviceworker
        生成一个 serviceworker 配置文件~
      */
      clientsClaim: true,
      skipWaiting: true
    })
  ],
  devServer: {//开发环境必有
    compress: true,// 启动gzip压缩
    contentBase: resolve(__dirname, 'build'),// 告诉服务器内容的来源。仅在需要提供静态文件时才进行配置。
    watchContentBase: true,// 监视 contentBase 目录下的所有文件,一旦文件变化就会 reload
    watchOptions: {
      ignored: /node_modules/// 忽略文件
    },
    port: 5000,// 端口号
    host: 'localhost',// 域名
    open: true,// 自动打开浏览器
    hot: true,// 开启HMR功能,需要插件webpack.HotModuleReplacementPlugin配合
    proxy: {// 服务器代理 --> 解决开发环境跨域问题
      '/api': {// 一旦服务器5000接收到'/api/xxx'的请求
        target: 'http://localhost:3000',//就会把请求转发到另外一个服务器3000
        pathRewrite: {// 发送请求时,请求路径重写:将/api去掉
          '^/api': ''
        }
      }
    },
    clientLogLevel: 'none',// 不要显示启动服务器日志信息
    quiet: true,// 除了一些基本启动信息以外,其他内容都不要显示
    overlay: false,// 如果出错了,不要全屏提示~
  },
  devtool: "nosources-source-map",//正常情况下,此配置项缺失比加上更好
  resolve: {// 解析模块的规则
    alias: {// 配置解析模块路径别名: 优点简写路径 缺点路径没有提示
      $css: resolve(__dirname, 'src/css')
    },
    extensions: ['.js', '.json', '.jsx', '.css'],// 配置省略文件路径的后缀名
    modules: [resolve(__dirname, '../../node_modules'), 'node_modules']// 告诉 webpack 解析模块是去找哪个目录
  }
  optimization: {
    /*
      1. 可以将node_modules中(除dll外)代码单独打包一个chunk最终输出
      2. 自动分析多入口chunk中,有没有公共的文件。如果有会打包成单独一个chunk
    */
    splitChunks: {
      chunks: 'all'
    }
  },
  externals: {//用CDN时,需要此项配置;用dll时不能有此项配置。
    jquery: "jquery", // 不打包第三方类库jquery
    vue: "vue", // 不打包第三方类库vue
  },
};
3、工程化优化之HMR,热模块替换。
(1)当webpack-dev-server运行时,不使用HMR,一个模块发生改变,所有模块都重新打包,最后浏览器重新渲染;使用HMR,一个模块发生改变,只会重新打包这一个模块,最后浏览器重新(请求)渲染。
(2)不采用尚硅谷的热模块方案,因为里面讲的是原理,当监听到变化时,执行的是函数,而不是打包和刷新。另外,后来我在写配置文件时,开发环境和生产环境,都用MiniCssExtractPlugin.loader,不用'style-loader'。
(3)采用热模块的正常方案,A、new webpack.NamedModulesPlugin(),获取热模块的模块名;B、new webpack.HotModuleReplacementPlugin()打包热模块
(4)没有重新请求的渲染不会导致控制台以前的数据丢失。
4、工程化优化之使用缓存
(1)通常情况下,在本地打包前端所有文件,然后上传给远端服务器的最终目录,替换掉原来的前端文件。这个替换时间比较长,有可能影响正常的网站访问。
(2)一般情况下,将改动的某个前端文件上传给远端服务器的临时目录,当只有js/css文件发生改变时,只打包js/css文件到最终目录里,在最终目录里,用最新的js/css文件名替换掉index.html上原来的文件名,这个替换时间比较短,同时删掉原来的js/css文件。
(3)使用缓存时,文件命名规则{filename: "js/built.[contenthash:10].js"/"css/built.[contenthash:10].css"}
5、工程化优化之去除无用代码
(1)tree shaking,摇树优化
(2)前提:必须使用ES6模块化、开启production环境
(3)作用: 减少代码体积
(4)在package.json中配置
  "sideEffects": false//所有代码都没有副作用(都可以进行tree shaking)  
  "sideEffects": ["*.css","*.less"]//.css、.less不要优化,因为优化可能会把@babel/polyfill文件删掉
6、工程化优化之多入口
(1)有多个入口、有多个输出、index.html有多个注入
示例
entry: {
  index: './src/js/index.js',
  test: './src/js/test.js'
},
(2)入口文件为单入口,但文件内部通过import动态导入语法,能将某个文件单独打包
(3)optimization:见上面配置项optimization
{
  /*
    1. 可以将node_modules中(除dll外--自悟)代码单独打包一个chunk最终输出
    2. 自动分析多入口chunk中,有没有公共的文件。如果有会打包成单独一个chunk
  */
  splitChunks: {
    chunks: 'all'
  }
},
7、工程化优化之PWA
(1)渐进式网络应用,可离线访问,英文为“Progressive Web App”,见上面插件WorkboxWebpackPlugin。
(2)eslint不认识 window、navigator全局变量。解决:需要修改package.json中eslintConfig配置
  "env": {
    "browser": true // 支持浏览器端全局变量
  }
(3)普通js文件  
  if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker
      .register('/service-worker.js')
      .then(() => {
        console.log('sw注册成功了~');
      })
      .catch(() => {
        console.log('sw注册失败了~');
      });
  });
}
8、工程化优化之dll
(1)对第三方库单独打包,如:jquery、react、vue...
(2)webpack.dll.js文件说明,用变量生成映射库
module.exports = {
  entry: {
    jquery: ["jquery"],
    vue: ["vue"],
  },
  output: {
    filename: '[name].js',
    path: resolve(__dirname, 'dll'),
    library: '[name]_[hash]' // 打包库里向外文件的名称
  },
  plugins: [
    new webpack.DllPlugin({ // 生成映射库
      name: "[name]_[hash]", // 映射库里文件的名称
      path: resolve(__dirname, "dll/manifest_[name].json"), // 输出多个文件时,文件名用变量
    }),
  ],
  mode: 'development'
};
(3)webpack.config.js文件说明,用列举使用映射库
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build')
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new webpack.DllReferencePlugin({// 使用映射库,把依赖的名称映射到built.js里模块的id上
      manifest: resolve(__dirname, "dll/manifest_jquery.json"),
    }),
    new webpack.DllReferencePlugin({// 使用映射库,把依赖的名称映射到built.js里模块的id上
      manifest: resolve(__dirname, "dll/manifest_vue.json"),
    }),
    new AddAssetHtmlWebpackPlugin([// 添加资源库,将资源打包出去,并在html中自动引入
      { filepath: resolve(__dirname, "dll/jquery.js") },// 有多项时,用数组
      { filepath: resolve(__dirname, "dll/vue.js") },// 只有一项时,直接用对象即可
    ]),
  ],
  mode: 'development',
};
9、其它优化方法
(1)oneOf:[],只执行数组选项中的一个
(2)将多次使用的加载器放到一个数组里,供展开使用
(3)懒加载,当需要使用文件时才加载,比如点击某个按钮后才加载某个文件
(4)多进程:见上面配置thread-loader
(5)不打包第三方类库:用externals排除第三方类库,用CND引入第三方库

三、三大框架之登录、权限、路由嵌套、状态管理、请求响应拦截
注:三大框架之登录和权限都走同一个逻辑
1、在angular1中,
$rootScope.$on('$stateChangeStart', function (event, toState) {
    myServer.changeState(event, toState);
    //changeState检验登陆状态
    //1、页面加载完毕,直接跳往登录页,2、登录成功后,跳往首页,3、根据登陆标志,向后台请求,获取权限信息,建立导航栏和选项卡。
  })  
(1)登录:页面加载完毕,根据$urlRouterProvider.otherwise('/login'),触发$stateChangeStart,不向后台发送请求。
(2)权限:登录成功后,跳转到首页,触发$stateChangeStart,向后台请求,获取权限信息,建立导航栏和选项卡。
(3)路由嵌套:<ui-view></ui-view>4)状态管理:ui-router
(5)请求响应拦截:$http
2、在vue中,
(1)登录:渲染index.html时,跳转到path: '/',执行router.beforeEach,检查是否登录;沒登录则跳转到path: '/login';
(2)权限:登录成功后,设置标志,跳转到path: '/',再次执行router.beforeEach;向后台获取权限信息。
(3)路由嵌套:<router-view></router-view>4)状态管理:vuex
(5)请求响应拦截:service.interceptors
const service = axios.create({
  baseURL: process.env.BASE_API,
  timeout: 15000
})
service.interceptors.request.use(function(){});
service.interceptors.response.use(function(){});
3、在react中,
(1)登录:渲染index.html时,跳转到path: '/',执行dispatch action,检查是否登录;沒登录则跳转到path: '/login';
(2)权限:登录成功后,设置标志,跳转到path: '/',再次执行dispatch action;向后台获取权限信息。
(3)路由嵌套:{React.Children.map}或{props.children}或<header><Route path="/user" component={UsersMenu}/></header>4)状态管理:react-redux
(5)请求响应拦截:service.interceptors
const service = axios.create({
  baseURL: process.env.BASE_API,
  timeout: 15000
})
service.interceptors.request.use(function(){});
service.interceptors.response.use(function(){});
4、导航、选项卡、页内按钮权限添加完毕后,进行无权限调试
(1)导航:if(条件)改为if(true)
(2)选项卡:维持原样
(3)页内按钮:在检验是否登陆的逻辑里,定义account_data.all_roles.indexOf = function () { return true;};
(4)其它数据,比如登录名、角色等,随意
(5)以上操作均在stateChange函数里
(6)点击登录时,直接跳转正在调试的那个状态

四、angular项目下index.html的注入与执行,
1、生产页面
<!DOCTYPE html>
<html lang="en" ng-controller="mainCtrl" ng-cloak>
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
    <title ng-bind="r_g_company.info.title"></title>
    <link rel="shortcut icon" ng-href="{{r_g_company.info.favicon}}"/>
    <link rel="stylesheet" href="/audit-html/static/common/bootstrap.css"/>
    <link rel="stylesheet" href="/audit-html/static/common/editor.md/css/editormd.min.css"/>
    <link rel="stylesheet" href="/audit-html/static/common/animate.min.css"/>
    <link rel="stylesheet" href="/audit-html/static/styles/all_73567.min.css"/>
  </head>
  <body ondragstart="return false;">
    <my-app></my-app>
  </body>
  <script src="/audit-html/static/common/jquery.js"></script>
  <script src="/audit-html/static/common/jquery-media.js"></script>
  <script src="/audit-html/static/common/echart.js"></script>
  <script src="/audit-html/static/common/webuploader.js"></script>
  <script src="../../static/scripts/all_yhg.min.js"></script>//回退一次就到根目录/audit-html了,再回退则忽略
</html>
2、index.html注入前页面
<!DOCTYPE html>
<html lang="en" ng-controller="mainCtrl" ng-cloak>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title ng-bind="r_g_company.info.title"></title>
<link rel="shortcut icon" ng-href="{{r_g_company.info.favicon}}">
<link rel="stylesheet" href="/audit-html/static/common/bootstrap.css">
<link rel="stylesheet" href="/audit-html/static/common/sliderCaptcha/slidercaptcha.css">
<!-- build:css(src) styles/all.min.css --> 下面的css将被打包
<!-- inject:css --> css将注入到下面
<link rel="stylesheet" href="module/policy/cy/policy-flow-watch.css">
<link rel="stylesheet" href="module/policy/cy/policy-Anti-attack.css">
<!-- endinject --> css将注入到上面
<!-- endbuild --> 上面的css将被打包
</head>
<body ondragstart="return false;">
  <my-app></my-app>
</body>
<script src="/audit-html/static/common/jquery.js"></script>
<script src="/audit-html/static/common/select.js"></script>
<!-- build:js(src) scripts/all.min.js --> 下面的js将被打包
<!-- inject:js --> js将注入到下面
<script src="config/main.js"></script>
<script src="module/role/cy/role-manage.js"></script>
<!-- endinject --> js将注入到上面
  <!-- inject:partials --> 特定js将注入到下面
  <!-- angular templates will be automatically converted in js and inserted here -->
  <!-- endinject --> 特定js将注入到上面
<!-- endbuild --> 上面的js将被打包
</html>
3、index.html注入后页面
<!DOCTYPE html>
<html lang="en" ng-controller="mainCtrl" ng-cloak>
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
  <title ng-bind="r_g_company.info.title"></title>
  <link rel="shortcut icon" ng-href="{{r_g_company.info.favicon}}">
  <link rel="stylesheet" href="/audit-html/static/common/bootstrap.css">
  <link rel="stylesheet" href="/audit-html/static/common/sliderCaptcha/slidercaptcha.css">
  <link rel="stylesheet" href="/audit-html/static/common/editor.md/css/editormd.min.css">
  <link rel="stylesheet" href="/audit-html/static/common/animate.min.css">
  <link rel="stylesheet" href="/audit-html/static/common/angular.treeview.css">
  <link rel="stylesheet" href="/audit-html/static/common/nprogress/nprogress.css">
  <!-- build:css(src) styles/all.min.css -->
  <!-- inject:css -->
  <link rel="stylesheet" href="module/common-css/animate.css">
  <link rel="stylesheet" href="module/common-css/boot-reset.css">
  <link rel="stylesheet" href="module/common-css/bower.css">
  <!-- endinject -->
  <!-- endbuild -->
</head>
<body ondragstart="return false;">
  <my-app></my-app>
</body>
<script src="/audit-html/static/common/jquery.js"></script>
<script src="/audit-html/static/common/jquery-media.js"></script>
<script src="/audit-html/static/common/sliderCaptcha/longbow.slidercaptcha.js"></script>
<script src="/audit-html/static/common/angular.js"></script>
<script src="/audit-html/static/common/angular-ui.js"></script>
<!-- build:js(src) scripts/all.min.js -->
<!-- inject:js -->
<script src="config/main.js"></script>
<script src="config/ctrl.js"></script>
<script src="config/project/cy/logo.js"></script>
<script src="config/project/cy/menu.js"></script>
<script src="module/common-serve/data-g.js"></script>
<script src="module/common-serve/date.js"></script>
......
<script src="module/role/cy/role-source.js"></script>
<!-- endinject -->
  <!-- inject:partials -->
  <!-- angular templates will be automatically converted in js and inserted here -->
  <!-- endinject -->
<!-- endbuild -->
</html>
4、index.html中,js文件从上到下执行
(1)执行main.js,
(A)注入依赖,当缓存中没有依赖key1、key2时,记依赖对象为{key1:null,key2:null,...},
(B)执行config和run
(2)执行main.js文件下面的js文件,当key1、key2出现时,key1、key2修改依赖对象为{key1:value1,key2:value2,...},
(3)所有js文件执行完毕以后,如果key1或key2...没有出现,则会报错,不会执行config和run的参数,否则会执行。
(4)在模块初始化时,config的参数执行,对模块进行配置;只在angular项目启动时,run的参数执行,定义全局的数据或逻辑。
注:每个Angular“应用程序”ng-app都有一个 injector ,负责创建并查找依赖。
注:angular服务,必须先注入到config、run或controller里,然后才能使用。
(4)在index.js中定义组件myApp
(function () {
  angular
    .module('common-dir', [])
    .directive('myApp', function () {
      console.log('myApp');
      var dirAlert = '<dir-alert></dir-alert>';
      var dirCommon = '<dir-common style="height:100%"></dir-common>';
      var dirTip = '<dir-tip></dir-tip>';
      var dirLoading = '<dir-load></dir-load>';
      var template = ''.concat(dirCommon, dirAlert, dirTip, dirLoading);
      return {
        restrict: 'E',
        template: template,
        scope: false,
        link: function () { }
      };
    });
})();
(5)在main.js中定义模块app
(function () {
  angular
    .module('app', [
      'ui.router',
      'angularTreeview',
      'common-serve',
      'module-login',
      'module-role',
    ])
    .config(function ($stateProvider, $urlRouterProvider, menu) {
      angular.forEach(menu, function (item) {
        angular.forEach(item.subs, function (it) {
          $stateProvider
            .state(it.state, it.cfg);
        });
      });
      $urlRouterProvider.otherwise('/login');
    })
    .run(function ($rootScope, account_m, app_init, account_data) {
      app_init
        .size_init()
        .key_init()
        .account_init();
      $rootScope.$on('$stateChangeStart',
        function (event, toState) {
          NProgress.start();
          account_m.start(event, toState);
        }
      );
      $rootScope.$on('$stateChangeSuccess',
        function (event, toState) {
          account_data.state = toState.name;
          NProgress.done();
        }
      );
    });
})();

五、安装服务器系统
1、通过FTP下载bin包至系统U盘
(1)bin包存放地址:192.168.80.892)FTP用户名:cy-version
(3)FTP密码:cy888888
(4)bin包存放路径:/versions/INA/INA-V2.0.4/5)下载bin包并存放至系统U盘
2、给服务器--插上--系统U盘
3、重启服务器(拔、插--电源,系统会自动安装成功,此过程耗时较长,点击COM3可以观看安装进程,出现OK和绿星,表示安装成功,此时服务器会自动断电)
4、给服务器--拔掉--系统U盘
5、重启服务器(拔、插--电源)

六、操作服务器系统
1、登陆服务器(用网线把我的电脑和服务器进行物理连接)
(1)打开Xshell,点击COM3,
(2)按enter键
(3)CyOS login: admin //xshell用户名4)Password:changyang123!@# //xshell密码5)CyOS# start //开启服务器6)Password:Cy@508# //服务器密码
2、给服务器配置IP
(1)root@CyOS:/root# ifconfig mgmt0 192.168.10.156(给接口配置IP。它有65535个端口,ifconfig(配置))mgmt0(接口))
(2)按enter键,IP配置成功
3、启动服务器
(1)root@CyOS:/root# cd /usr/local/audit-web
(2)root@CyOS:/usr/local/audit-web# python manage.py runserver
4、辅助步骤
(1)Ctrl+C(退出进程)
(2)root@CyOS:/usr/local/audit-web# pkill -f python -9(杀死python进程,出现Address already in use时,需要用到这个命令)
(3)root@CyOS:/usr/local/audit-web# pkill -f uwsgi -9(杀死名为uwsgi的进程)
(4)root@CyOS:/usr/local/audit-web# iptables -P INPUT ACCEPT(关闭防火墙,P INPUT ACCEPT均大写)
(5)root@CyOS:/usr/local/audit-web# ps aux|grep python(查看活进程,aux显示所有进程和进程状态,grep在这些里搜索)
(6)root@CyOS:/root# ifconfig(显示或设置网络设备)/////////////////////////7)root@CyOS:/root# cat /usr/local/etc/suricata/version.autogen(查看当前版本)
(8)服务器重启:A、192.168.10.59不会丢失IP;B、192.168.10.156:5000会丢失ip;C、经过在审计项目进行如下操作设置-IP设置-设置本机IP-192.168.10.156-255.255.255.0-192.168.10.1后,ip不会丢失。

七、Linux,ubuntu和VMware
1、负载均衡
(1)CDN部署在网络提供商的机房,反向代理部署在网站的机房;
(2)正向代理:客户端通过代理服务器向服务器发送请求,隐藏了真实的客户端;
(3)反向代理:客户端访问代理服务器,代理服务器返回缓存内容,隐藏了真实的服务端;
(4)Nginx:性能非常好的反向代理服务器,用来做负载均衡,可以在Linux系统中运行。
2、服务器硬件连接
(1)电源(服务器连到电源插座)
(2)网线(服务器连接外网,可以通过ip访问)
(3)主机(服务器通过COM连接自己的主机,可以直接访问)
3、Xshell新建
(1)新建串行接口COM3:文件-新建-名称(N):COM3,协议(P):SERIAL
(2)新建远程接口NUMB:文件-新建-名称(N):192.168.10.156,协议(P):SSH,主机(H):192.168.10.156
4、“rm -rf”释义
(1)rm:remove;移除
(2)r:recursion;[rɪˈkɜːʃn];递归
(3)f:force;强制
5、Linux,ubuntu和VMware之间的关系
(1)Linux是一个操作系统;
(2)Ubuntu是一个以桌面应用为主的Linux操作系统
(3)VMware是虚拟主机,在安装的过程中,导入ubuntu
(4)在ubuntu里,应该用Linux命令来操作里面的文件
(5)安装步骤;点击VMware.exe文件直到结束-->点击桌面VMware图标-->点击“创建新的虚拟机”-->安装依赖(最后一步,耗时约40分钟)
(6)4步完全卸载VMware。A、关闭VMware;B、应用卸载-->vmware-->修改-->下一步-->删除;C、C:\Program Files (x86)下删除VMware;D、C:\Users\用户名\Documents下删除Virtual Machines,内含ubuntu 
6、在Ubuntu16.0.4里,基本操作
(1)获得超级用户权限:sudo su
(2)重启虚拟机sudo reboot
(3)安装包sudo apt-get install package
(4)修复包sudo apt-get -f install
(5)apt-get,是一条linux命令,用于自动从互联网的软件仓库中搜索、安装、升级、卸载软件或操作系统。
(6)apt是Linux下的一款安装包管理工具,apt = apt-get + apt-cache + apt-config

八、在Ubuntu16.0.4里,安装搜狗输入法和谷歌浏览器
1、安装简体中文输入法:
(1)设置-系统设置-语言支持-安装-密码-确认-(安装fcitx,耗时约10分钟)
(2)语言-安装/卸载语言-(勾选)中文简体-应用-密码-确认-(安装字体,耗时约10分钟)
(3)区域格式-汉语中国-语言-(汉语中国)拉到第一位-(键盘输入法系统)fcitx-关闭
(4)删除包sudo apt-get remove fcitx-ui-qimpanel
附1:Fcitx是(Free Chinese Input Toy for X)的英文缩写,可为支持 XIM 的 X 应用程序提供输入服务。可以输入UTF-8编码中的汉字。
2、安装搜狗输入法
(1)下载搜狗输入法安装包http://pinyin.sogou.com/linux,进入下载目录cd Downloads2)安装搜狗输入法sudo dpkg -i sogoupinyin_2.4.0.3469_amd64.deb
(3)重启虚拟机sudo reboot
(4)文字图标-配置当前输入法-(搜狗输入法个人版)调至第一个选项
3、安装过程中,可能遇到的问题及解决
问题1:updating cache ; waiting for apt-get to exit
解决1:sudo fuser -vki /var/lib/apt/lists/lock
问题2:由于找不到vcruntime140_1.dll,无法继续执行代码重新安装程序可能会解决此问题
解决2:下载文件vcruntime140_1.dll,复制到32/64位版本电脑的的C:\Windows\system64/32下
问题3:搜狗输入时出现乱码
解决3:killall fcitx
3、安装谷歌浏览器
(1)sudo wget http://www.linuxidc.com/files/repo/google-chrome.list -P /etc/apt/sources.list.d/2)wget -q -O - https://dl.google.com/linux/linux_signing_key.pub  | sudo apt-key add -3)sudo apt-get update
(4)sudo apt-get install google-chrome-stable
(5)/usr/bin/google-chrome-stable
(6)在屏幕左侧的图标上,右键“锁定到启动器”

九、electron
1、electron是什么?
(1)用Web技术构建跨平台的桌面应用,electron = Chromium + Node.js + Native API。20165 月 Electron 发布了 v1.0.0 版本
(2)Chromium,为 Electron 提供了强大的UI能力,可以不考虑兼容性的情况下,利用强大的Web生态来开发界面
(3)Node.js,让 Electron 有了底层的操作能力,比如文件的读写,甚至是集成C++等等操作,并可以使用大量开源的 npm 包来完成开发需求
(4)Native API,Native API 让 Electron 有了跨平台和桌面端的原生能力,比如说它有统一的原生界面,窗口、托盘这些。
2、什么时候使用Electron?
(1)公司没有专门的桌面应用开发者,而需要前端兼顾来进行开发时,用Electron就是一个不错的选择。
(2)一个应用需要同时开发Web端和桌面端的时候,那使用Electron来进行开发就对了。
(3)开发一些效率工具,比如API类的工具。
 
十、服务端渲染
1、服务端渲染:服务器收到请求后,把数据拼接到html里,发送给浏览器渲染。
2、客户端渲染:服务器收到请求后,发送数据给浏览器,浏览器用js把数据拼接到html里,然后渲染。
3、怎样查看客户端首次渲染:
(1)把http://localhost:8000粘贴到浏览器2)打开控制台console
(3)刷新浏览器
 
十一、__dirname|join|resolve
1、__dirname和join
var path = require("path");
console.log(__dirname); c:\Users\公司\Desktop\yuanma
console.log(path.join(__dirname, "..", "src")); c:\Users\公司\Desktop\src
console.log(path.join(__dirname, "../", "src")); c:\Users\公司\Desktop\src
2、__dirname和resolve
var path = require("path");
console.log(__dirname); c:\Users\长扬科技\Desktop\yuanma
console.log(path.resolve(__dirname, "..", "src")); c:\Users\长扬科技\Desktop\src
console.log(path.resolve(__dirname, "../", "src")); c:\Users\长扬科技\Desktop\src
 
十二、npm|cnpm|yarn|tyarn|bootstrap
1、npm:最常用的包管理器。
2、cnpm:是npm的国内镜像。
3、yarn:是2016年重新设计发布的npm客户端,是并行下载的
4、tyarn:是yarn的国内镜像了。
5、npm install 安装命令示例,包名和后面的参数,位置可以互换。
(1)npm install 把package.json中的依赖配置,下载到本地项目的node_modules
(2)npm install X 会把X包安装到项目的node_modules目录中,不会将模块依赖写入package.json中。
(3)npm install X -g 会把X包安装到全局的node_modules目录中,不会将模块依赖写入package.json中。
(4)npm install X --save 会把X包安装到项目的node_modules目录中,会在package.json的dependencies属性下添加X
(5)npm install X --save-dev 会把X包安装到项目的node_modules目录中,会在package.json的devDependencies属性下添加X
6、npm其它命令
(1)npm help <command>可查看某条命令的详情
(2)npm update <package>可以把当前目录下node_modules子目录里边的对应模块更新至最新版本
7、bootstrap
(1)n.[计]辅助程序
(2)vt.启动(电脑)
 

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM