Code Monkey home page Code Monkey logo

webpack's People

Contributors

pleasestartyourperformance avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

webpack's Issues

Webpack-mini-css-extract-plugin

mini-css-extract-plugin

webpack 4.0以前,我们通过extract-text-webpack-plugin插件,把css样式从js文件中提取到单独的css文件中。extract-text-webpack-plugin插件的优缺点:

在webpack4.0出现后使用mini-css-extract-plugin插件来打包css文件。

//安装
yarn add -D mini-css-extract-plugin

这个插件应该只用在 production 配置中,并且在loaders链中不使用 style-loader, 特别是在开发中使用HMR,因为这个插件暂时不支持HMR

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const devMode = process.env.NODE_ENV !== 'production';

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      filename: devMode ? '[name].css' : '[name].[hash].css',
      chunkFilename: devMode ? '[id].css' : '[id].[hash].css',
    })
  ],
  module: {
    rules: [
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader',
          'sass-loader',
        ],
      }
    ]
  }
}

还有个简单的例子

{
    entry: {
        index: "../src/index.js",
        utils: '../src/utils.js',
    },
    output: {
        filename: "[name].bundle.js", // 输出 index.js 和 utils.js
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader, // 创建一个 link 标签
                    'css-loader', // css-loader 负责解析 CSS 代码, 处理 CSS 中的依赖
                ],
            },
        ]
    }
    plugins: [
        // 用 MiniCssExtractPlugin 抽离出 css 文件,以 link 标签的形式引入样式文件
        new MiniCssExtractPlugin({
            filename: 'index.bundle.css' // 输出的 css 文件名为 index.css
        }),
    ]
}

Webpack-loader中配置include和exclude作用

const path = require('path');
{
    module: {
        loaders: [{
            test: /\.js$/,
            loader: 'babel-loader',
            include: [
                path.resolve(__dirname, "app/src"),
                path.resolve(__dirname, "app/test")
            ],
            exclude: /node_modules/
           // exclude: [/node_modules/,/xxx/] 数组写法

        }]
    }
}

include:表示哪些目录下的.js需要 babel-loader
exclude:表示哪些目录下的.js需要 不需要babel-loader

Pagejson-npm包中的命令封装,项目中使用

疑问:pagejson中类似这种自定义命令是哪里来的-原理是什么

image

解答:

在package.json包中提供了一个映射到本地文件名的bin字段

image

之后npm包将链接这个文件到prefix/fix里面,以便全局引入。或者链接到本地的node_modules/.bin/文件中,以便在本项目中使用。

在node_modules/.bin/中

image

webpack-tpl文件模板使用

路径:scripts

generate.js

#!/usr/bin/env node

const path = require('path');
const fs = require('fs-extra');
const inquirer = require('inquirer');

const templatePath = path.join(__dirname, 'template');
const srcPath = path.join(__dirname, '../src');

const comps = require('../components.json');


const contentReplace = (content, data) => {
  return content.replace(/__COMPONENT_NAME__/g, data.componentName)
    .replace(/__COMPONENT_CLASS_NAME__/g, data.componentClassName)
    .replace('__COMPONENT_FILENAME__', data.componentFileName)
    .replace('__COMPONENT_TAG_NAME__', data.componentFileName)
    .replace('__STORIES_ORDER__', data.storiesOrder)
    .replace(/.tpl$/g, '');

}

const fileGen = (srcPath, distPath, data) => {
  const files = fs.readdirSync(srcPath);
  files.forEach(file => {
    const fileContent = fs.readFileSync(path.join(srcPath, file));
    let fileString = fileContent.toString();
    fileString = contentReplace(fileString, data);
    file = contentReplace(file, data);
    fs.ensureDirSync(distPath);
    fs.writeFileSync(distPath + '/' + file, fileString)
    console.log(distPath + '/' + file)
  })
};

const componentsPath = path.join(srcPath, 'components');
const storiesPath = path.join(srcPath, 'stories');
const typesPath = path.join(__dirname, '../types');
const indexFilePath = path.join(componentsPath, 'index.ts');
const xinUiDFilePath = path.join(typesPath, 'xin-ui.d.ts');
const stories = fs.readdirSync(storiesPath);
const storiesOrder = stories.filter(s => fs.statSync(path.join(storiesPath, s)).isDirectory()).length;


function gen(inputName) {
  if(/^(x|X)in*/i.test(inputName)) {
    console.log(`组件: [${inputName}] 不能以 (x|X)in* 开头,程序内会自动补充,换个名字再试试吧!!!`);
    process.exit(1)
    return;
  }

  if(Object.keys(comps).length) {
    let compKeys = Object.keys(comps);
    let _inputName = inputName.replace(/[-_](\w)/g, function (all, letter) {
      return letter.toUpperCase();
    }).replace(/^(\w)/, function (all, letter) {
      return letter.toUpperCase();
    });

    if(compKeys.includes(`Xin${_inputName}`)) {
      console.log(`组件: [Xin${_inputName}] 已存在,请尝试其他名字再试试!!!`);
      process.exit(1)
      return;
    }
  }

  const data = {
    componentName: inputName.replace(/[-_](\w)/g, function (all, letter) {
      return letter.toUpperCase();
    }).replace(/^(\w)/, function (all, letter) {
      return letter.toUpperCase();
    }),
    componentClassName: inputName,
    componentFileName: inputName,
    componentsXinName: `xin-${inputName}`,
    storiesOrder: storiesOrder
  }

  const indexFile = fs.readFileSync(indexFilePath);
  let indexFileString = indexFile.toString()
  indexFileString = indexFileString.replace(
    /(import\s+.*\s+from\s+.*\n)(\n+[^import])/,
    `$1import Xin${data.componentName} from './xin-${data.componentFileName}/index';\n$2`
  ).replace(
    /(const\s+components\s+=\s+\[.*\n)((.*,\n)+)(.*)(\n\])/,
    `$1$2$4,\n  Xin${data.componentName}$5`
  ).replace(
    /(export\s+\{.*\n)((.*,\n)+)(.*)(\n\})/,
    `$1$2$4,\n  Xin${data.componentName}$5`
  )

  const xinUiDFile = fs.readFileSync(xinUiDFilePath)
  let xinUiDFileString = xinUiDFile.toString();
  xinUiDFileString = xinUiDFileString.replace(
    /(import\s+.*\s+from\s+.*\n)(\n+[^import])/,
    `$1import {Xin${data.componentName}} from './components/xin-${data.componentFileName}';\n$2`
  ).replace(
    /(export\s+\{.*\n)((.*,\n)+)(.*)(\n\})/,
    `$1$2$4,\n  Xin${data.componentName}$5`
  )

  fileGen(path.join(templatePath, 'components'), path.join(componentsPath, data.componentsXinName), data);
  fileGen(path.join(templatePath, 'componentsIndex'), path.join(componentsPath, data.componentsXinName), data);
  fileGen(path.join(templatePath, 'stories'), path.join(storiesPath, data.componentFileName), data);
  fileGen(path.join(templatePath, 'types'), path.join(typesPath, 'components'), data);
  fs.writeFileSync(indexFilePath, indexFileString);
  fs.writeFileSync(xinUiDFilePath, xinUiDFileString);
}

const inputName = process.argv[2];
if (!inputName) {
  inquirer.prompt([
    {
      type: 'input',
      name: 'componentName',
      message: '请输入要创建的组件名称:'
    }
  ]).then(answers => {
    if (answers.componentName) {
      gen(answers.componentName)
    }
  })
} else {
  gen(inputName)
}

模板文件

image

tpl文件代码用法

<template>
  <div class="xin-__COMPONENT_CLASS_NAME__">
    __COMPONENT_NAME__
  </div>
</template>

<script lang="ts">
  import {Vue, Component} from 'vue-property-decorator';

  @Component({
    name: "xin-__COMPONENT_CLASS_NAME__"
  })
  export default class Xin__COMPONENT_NAME__ extends Vue {
  }
</script>

<style scoped lang="scss">
  .xin-__COMPONENT_CLASS_NAME__ {
  }
</style>

import {Xin__COMPONENT_NAME__} from '../../components';
import Readme from './__COMPONENT_FILENAME__.md';

export default {
  title: '__COMPONENT_NAME__',
  component: Xin__COMPONENT_NAME__,
  parameters: {
    order: __STORIES_ORDER__,
    notes: Readme
  }
};

export const Default = () => ({
  components: {Xin__COMPONENT_NAME__},
  template: `
    <div class="demo-__COMPONENT_CLASS_NAME__">
      <xin-__COMPONENT_TAG_NAME__ />
    </div>
  `
});

Webpack-VUEcli3的配置

掘金博客:https://juejin.im/post/5c6e608c5188256283255704#heading-14

官网:https://cli.vuejs.org/zh/config/#publicpath

publicPath:路由中的设置

Vue CLI 会假设你的应用是被部署在一个域名的根路径上,例如 https://www.my-app.com/。
如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.my-app.com/my-app/ 则设置 publicPath 为 /my-app/

这个值也可以被设置为空字符串 ('') 或是相对路径 ('./'),这样所有的资源都会被链接为相对路径,这样打出来的包可以被部署在任意路径,也可以用在类似 Cordova hybrid 应用的文件系统

outputDir

当运行 vue-cli-service build 时生成的生产环境构建文件的目录。注意目标目录在构建之前会被清除

assetsDir

放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录。
从生成的资源覆写 filename 或 chunkFilename 时,assetsDir 会被忽略。

webpack-inquirer.js——⼀个⽤户与命令⾏交互的⼯具

开始通过npm init 创建package.json的时候就有⼤量与⽤户的交互(当然也可以通过参数来忽略输⼊);⽽现在⼤多数⼯程都是通过脚⼿架
来创建的,使⽤脚⼿架的时候最明显的就是与命令⾏的交互,如果想⾃⼰做⼀个脚⼿架或者在某些时候要与⽤户进⾏交互,这个时候就不得
不提到inquirer.js了。
介绍
由于交互的问题种类不同,inquirer为每个问题提供很多参数:
type:表⽰提问的类型,包括:input, confirm, list, rawlist, expand, checkbox, password, editor;
name: 存储当前问题回答的变量;
message:问题的描述;
default:默认值;
choices:列表选项,在某些type下可⽤,并且包含⼀个分隔符(separator);
validate:对⽤户的回答进⾏校验;
filter:对⽤户的回答进⾏过滤处理,返回处理后的值;
transformer:对⽤户回答的显⽰效果进⾏处理(如:修改回答的字体或背景颜⾊),但不会影响最终的答案的内容;
when:根据前⾯问题的回答,判断当前问题是否需要被回答;
pageSize:修改某些type类型下的渲染⾏数;
prefix:修改message默认前缀;
suffix:修改message默认后缀。

语法结构

const inquirer = require('inquirer');
const promptList = [
    // 具体交互内容
];
inquirer.prompt(promptList).then(answers => {
    console.log(answers); // 返回的结果
})

Webpack-添加数组原生方法

入口文件中

const {getPlugins} = require('./utils/getPlugins');
const {getEntries} = require('./utils/getEntries');
const {getLoaders} = require('./utils/getLoaders');
const {getAlias} = require('./utils/getAlias');
const path = require('path');

module.exports = {
    entry: getEntries(),//注意这里------------------------------
    output: {
        path: path.join(__dirname, '../dist'),
    },
    resolve: {
        extensions: ['.js', '.ts', '.tsx', '.less', '.css'],
        alias: getAlias()
    },
    stats: 'errors-only',
    module: {
        rules: getLoaders()
    },
    optimization: {
        splitChunks: {
            chunks: 'all',
            name: 'chunk'
        }
    },
    plugins: getPlugins()
};

getEntries

const resolve = require('./index').resolve;

function getEntries() {
    return {
        bundle: [
            resolve('./src/old-pages/js/tags-dep.js'),
            resolve('./src/old-pages/js/router.js'),
            resolve('./src/old-pages/js/boot.js'),

            resolve('./thirdsrc/froala/js/froala_editor.js'),
            resolve('./thirdsrc/froala/js/plugins/align.min.js'),
            resolve('./thirdsrc/froala/js/plugins/colors.min.js'),
            resolve('./thirdsrc/froala/js/plugins/draggable.min.js'),
            resolve('./thirdsrc/froala/js/plugins/font_size.min.js'),
            resolve('./thirdsrc/froala/js/plugins/font_family.min.js'),
            resolve('./thirdsrc/froala/js/plugins/fullscreen.min.js'),
            resolve('./thirdsrc/froala/js/plugins/image.js'),
            resolve('./thirdsrc/froala/js/plugins/image_manager.min.js'),
            resolve('./thirdsrc/froala/js/plugins/line_breaker.min.js'),
            resolve('./thirdsrc/froala/js/plugins/link.js'),
            resolve('./thirdsrc/froala/js/plugins/lists.min.js'),
            resolve('./thirdsrc/froala/js/plugins/paragraph_format.min.js'),
            resolve('./thirdsrc/froala/js/plugins/table.min.js'),
            resolve('./thirdsrc/froala/js/plugins/url.min.js'),
            resolve('./thirdsrc/froala/js/plugins/word_paste.js'),
            resolve('./thirdsrc/froala/js/languages/zh_cn.js'),
        ]
    };
}
exports.getEntries = getEntries;

tags-dep.js (数组原生添加方法)

/* eslint-disable */

/*
 *  数组方法扩展
 */
if (![].indexOf) {
    Array.prototype.indexOf = function(val) {
        for (var i = 0; i < this.length; i++) {
            if (this[i] == val) return i;
        }
        return -1;
    };
}
Array.prototype.remove = function(val) {
    var index = this.indexOf(val);
    if (index > -1) {
        this.splice(index, 1);
    }
};

Array.prototype.removeBy = function(key, val) {
    for (var i = 0; i < this.length; i++) {
        if (Object.prototype.toString.call(this[i]) === '[object Object]') {
            if (this[i][key] === val) {
                this.splice(i, 1);
            }
        }
    }
};

Array.prototype.unique = function() {
    var res = [];
    var json = {};
    for (var i = 0; i < this.length; i++) {
        if (!json[this[i]]) {
            res.push(this[i]);
            json[this[i]] = 1;
        }
    }
    return res;
};

Array.prototype.clone = function() {
    return [].concat(this);
};

Webpack-webpack面试题(2)

有哪些常见的Loader?他们是解决什么问题的?

  • file-loader:把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件
  • url-loader:和 file-loader 类似,但是能在文件很小的情况下以 base64 的方式把文件内容注入到代码中去
  • source-map-loader:加载额外的 Source Map 文件,以方便断点调试
  • image-loader:加载并且压缩图片文件
  • babel-loader:把 ES6 转换成 ES5
  • css-loader:加载 CSS,支持模块化、压缩、文件导入等特性
  • style-loader:把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS。
  • eslint-loader:通过 ESLint 检查 JavaScript 代码

有哪些常见的Plugin?他们是解决什么问题的?

  • define-plugin:定义环境变量
  • commons-chunk-plugin:提取公共代码
  • uglifyjs-webpack-plugin:通过UglifyES压缩ES6代码

如何利用webpack来优化前端性能?(提高性能和体验)

用webpack优化前端性能是指优化webpack的输出结果,让打包的最终结果在浏览器运行快速高效。

压缩代码。删除多余的代码、注释、简化代码的写法等等方式。可以利用webpack的UglifyJsPlugin和ParallelUglifyPlugin来压缩JS文件, 利用cssnano(css-loader?minimize)来压缩css
利用CDN加速。在构建过程中,将引用的静态资源路径修改为CDN上对应的路径。可以利用webpack对于output参数和各loader的publicPath参数来修改资源路径
删除死代码(Tree Shaking)。将代码中永远不会走到的片段删除掉。可以通过在启动webpack时追加参数--optimize-minimize来实现
提取公共代码。

https://zhuanlan.zhihu.com/p/44438844

Webapck-merge

const merge = require('webpack-merge');

用webpack-merge将配置文件拆分为3个文件,一个是webpack.base.conf.js,即不管是生产环境还是开发环境都会用到的部分,以及webpack.prod.conf.js和webpack.dev.conf.js, 并且使用webpack-merge来合并对象

image

Webpack-优化

BundleAnalyzerPlugin

分析资源大小

SpeedMeasurePlugin

分析每个步骤花费的时间
优化工具

hard-source-webpack-plugin

可以看到,启用这个插件后,loader不占用1s编译时间。因为上次所有的编译内容都被缓存了,新的编译只需要做增量编译即可,不需要重复编译。
image

安装

npm install --save-dev hard-source-webpack-plugin
# or
yarn add --dev hard-source-webpack-plugin

配置

// webpack.config.js
var HardSourceWebpackPlugin = require('hard-source-webpack-plugin');

module.exports = {
  context: // ...
  entry: // ...
  output: // ...
  plugins: [
    new HardSourceWebpackPlugin()
  ]
}

HardSourceWebpackPlugin 和 speed-measure-webpack-plugin 不能一起使用

原文链接

https://juejin.im/post/6887863430510968839?utm_source=gold_browser_extension

Jenkins-部署前端服务

使用git

image

构建触发器

构建触发器配置,需要勾选“build when a change is pushed to gitlab. GitLab CI Service URL:http://10.11.3.26:8080/project/test”该项(注意:只有jenkins安装了gitlab hook plugin插件后,才有该项,不安装是没有该选项的)

image

构建环境

可以选择这两项
Add timestamps to the Console Output:为控制台添加时间戳
Color ANSI Console Output:彩色控制台

构建

选择执行shell

示例

image

/home/tsingsoft/websites为linues下的目录

image

Webpack- webpack 的gzip 和 nginx gzip的区别

问题:webpack打包时已经进行gzip压缩了,那为什么还要再次开启nginx的gzip压缩呢?

nginx分为实时gzip和静态gzip, 所谓实时gzip就是无论你的静态资源有没有压缩,我都给你使用gzip压缩一次,所谓静态gzip,就是当你请求某个静态资源时,我先找下该静态资源有没有对应的gz文件,如果有,那nginx就直接使用gz文件,而不再进行实时gzip压缩, 从而减少了nginx对cpu的使用,加快了响应速度. 不过要使用静态gzip必须要先启用nginx的gzip_static 模块.

Webpaqck-webpack面试题(1)

webpack3和webpack4的区别

1.1. mode/–mode参数
新增了mode/--mode参数来表示是开发还是生产(development/production)
production 侧重于打包后的文件大小,development侧重于goujiansud
1.2. 移除loaders,必须使用rules(在3版本的时候loaders和rules 是共存的但是到4的时候只允许使用rules)
1.3. 移除了CommonsChunkPlugin (提取公共代码),用optimization.splitChunks和optimization.runtimeChunk来代替
1.4. 支持es6的方式导入JSON文件,并且可以过滤无用的代码

let jsonData = require('./data.json')
import jsonData from './data.json'
import { first } from './data.json' // 打包时只会把first相关的打进去

1.5. 升级happypack插件(happypack可以进行多线程加速打包)
1.6. ExtractTextWebpackPlugin调整,建议选用新的CSS文件提取kiii插件mini-css-extract-plugin,production模式,增加 minimizer

loader 和 plugin 不同

2.1. loader是使wenbpack拥有加载和解析非js文件的能力
2.2. plugin 可以扩展webpack的功能,使得webpack更加灵活。可以在构建的过程中通过webpack的api改变输出的结果

webpack与grunt、gulp的不同?

三者都是前端构建工具,grunt和gulp在早期比较流行,现在webpack相对来说比较主流,不过一些轻量化的任务还是会用gulp来处理,比如单独打包CSS文件等。

grunt和gulp是基于任务和流(Task、Stream)的。类似jQuery,找到一个(或一类)文件,对其做一系列链式操作,更新流上的数据, 整条链式操作构成了一个任务,多个任务就构成了整个web的构建流程。

webpack是基于入口的。webpack会自动地递归解析入口所需要加载的所有资源文件,然后用不同的Loader来处理不同的文件,用Plugin来扩展webpack功能。

所以总结一下:

从构建思路来说
gulp和grunt需要开发者将整个前端构建过程拆分成多个Task,并合理控制所有Task的调用关系
webpack需要开发者找到入口,并需要清楚对于不同的资源应该使用什么Loader做何种解析和加工
对于知识背景来说
gulp更像后端开发者的思路,需要对于整个流程了如指掌 webpack更倾向于前端开发者的思路

Webpack-devServer使用和基本配置

devServer

compress:一切服务都启用gzip 压缩
open:true启用“打开”后,开发服务器将打开浏览器。
changeOrigin: true,将主机头的来源更改为目标URL
pathRewrite:重写cookie头路径

常规写法

 devServer: {
        compress: true,
        open: true,
        proxy: {
            '/api': {
                target: 'http://39.99.148.210:1001',
                changeOrigin: true,
                pathRewrite: {
                    '^/api': '/'
                }
            }
        }
    },

链式写法

 config.devServer
            .compress(true)
            .open(true)
            .proxy({
                    '/api': {
                    target: 'http://39.99.148.210:1001',
                    changeOrigin: true,
                    pathRewrite: {
                        '^/api': '/'
                    }
                }
            })

源码连接:https://github.com/chimurai/http-proxy-middleware#options
webpack文档:https://www.webpackjs.com/configuration/dev-server/#devserver-proxy

Webpack-Vue.config.js全局引入@时配置和gzip以及devServer

    chainWebpack: (config) => { 
//@代表外面的src哦
 config
            .resolve
            .alias
            .set('@', resolve('src'))
            .set('static', resolve('public/static'));

        config
            .plugin('gzip')
            .use(CompressionWebpackPlugin, [{
                algorithm: 'gzip',
                test: new RegExp(
                    '\\.(' + ['js', 'css'].join('|') +
                    ')$'
                ),
                threshold: 1024,
                minRatio: 0.8
            }])
   config.devServer
            .compress(true)
            .open(true)
            .proxy({
                    '/api': {
                    target: 'http://39.99.148.210:1001',
                    changeOrigin: true,
                    pathRewrite: {
                        '^/api': '/'
                    }
                }
            })
}

不使用链式

    devServer: {
        compress: true,
        open: false, //启动项目自动打开浏览器
        proxy: { //代理
            '/api': {
                target: 'http://192.168.0.37:3001',
                changeOrigin: true,
                pathRewrite: {
                    '^/api': '/'
                }
            }
        }
    },

Webpack-postcss-loader和autoprefixer处理浏览器兼容问题

在webpack中需要处理css必须先安装如下两个loader

npm install --save-dev css-loader style-loader

要处理css和添加浏览器前缀需要下载如下插件和loader

//sass-loader依赖于node-sass,所以还要安装node-sass
//postcss-loader autoprefixer postcss 处理浏览器兼容
npm install --save-dev  postcss-loader autoprefixer postcss

webpack配置

{
     test:/\.css$/,
                use: ExtractTextPlugin.extract({
                    fallback: 'style-loader',
                    use: [
                        { 
                            loader: 'css-loader', 
                            options: { importLoaders: 1 } 
                        },
                        'postcss-loader'
                    ]
                }),
 }

结果:
image

webpack-eslintrc.js配置

/**
 * 参考文档
 * 【eslint英文文档】https://eslint.org/docs/user-guide/configuring
 * 【eslint中文文档】http://eslint.cn/docs/rules/
 */

/**
 * eslint有三种使用方式
 * 【1】js代码中通过注释的方式使用
 * 【2】通过webpack的eslintConfig字段设置,eslint会自动搜索项目的package.json文件中的配置
 * 【3】通过配置文件的方式使用,配置文件有多种文件方式,如JavaScript、JSON 或者 YAML等
 */

/**
 * 文件忽略
 * 【】让eslint跳过特定文件的检测
 * 【】通过当前工作目录下 「.eslintignore」 文件进行设置
 *    其使用的是Glob路径书写方式,与「.gitignore」的使用方法相同
 * 【】也可以在 package.json 文件中,通过 eslintIgnore 参数进行设置
 */

/**
 * 文件内局部设置
 * 【】eslint可以具体文件中设置特定代码的规则,常用于跳过某条语句的检测。
 * 【】注销全部规则,在代码前新建一行,添加注销 /* eslint-disable *\/   。如果没有恢复设置的语句,则下列全部代码都会跳过检测。
 * 【】恢复eslint,在代码前新建一行,添加注销 /* eslint-enable *\/
 * 【】指定忽略的规则,/* eslint-disable no-alert, no-console *\/
 * 【】在特定行禁用,// eslint-disable-line
 * 【】在下一行禁用,// eslint-disable-next-line
 */

module.exports = {

  /**
   * 根目录标识
   *  http://eslint.cn/docs/user-guide/configuring#using-configuration-files
   *  http://eslint.cn/docs/user-guide/configuring#configuration-cascading-and-hierarchy
   * 【】标识当前配置文件为最底层的文件,无需往更上一级的文件目录中进行搜索
   * 【】默认eslint的配置文件搜索方式是,从目标文件夹进行搜索,遍历内部每一个文件夹,找到配置文件并层叠使用。再跳出本项目,往祖先文件夹进行遍历
   * 【】注意「~/.eslintrc」的意义,「~」是指linux上的家目录,「~/.eslintrc」是指家目录下的eslint配置文件,用于私人开发者,用于整个电脑全局约束的。这个配置通过本配置项root去设置,设置了root,eslint检测时将不会再往上搜索
   * 【】eslint的生效规则是就近使用,越近的配置项优先级越高,覆盖其他配置项。如一个项目中,可以在不同文件夹中都添加配置文件,这些规则将重叠组合生效
   */
  root: true, // 标识当前配置文件为eslint的根配置文件,让其停止在父级目录中继续寻找。


  /**
   * 解析器
   *  http://eslint.cn/docs/user-guide/configuring#specifying-parser
   * 【】ESLint 默认使用Espree作为其解析器
   * 【】解析器必须是本地安装的一个 npm 模块。即必须按照在本地的node_module中
   * 【】解析器是用于解析js代码的,怎么去理解每一个表达式,有点C++中编译器的概念,会对js进行一些语法分析,语义分析什么的,才能判断语句符不符合规范。而不是通过简单的字符串对比。
   * 【】解析器有很多,但兼容eslint的解析器有以下几个
   *  Espree:默认解析器,一个从Esprima中分离出来的解析器,做了一些优化
   *  Esprima:js标准解析器
   *  Babel-ESLint: 一个对Babel解析器的包装,babel本身也是js解析器的一种(不然怎么能转化为兼容性代码呢?首先需要进行js解析,才能转化)。如果我们的代码需要经过babel转化,则对应使用这个解析器
   *  typescript-eslint-parser(实验) - 一个把 TypeScript 转换为 ESTree 兼容格式的解析器
   * 【】但是通常在vue项目中,并不会写在 parser 字段中,而是写在 parserOptions -> parser。具体原因在 parserOptions 一栏中介绍
   */
  // parser: 'babel-eslint',


  /**
   * 解析器配置项
   *  http://eslint.cn/docs/user-guide/configuring#specifying-parser-options
   * 【】这里设置的配置项将会传递到解析器中,被解析器获取到,进行一定的处理。具体被利用到,要看解析器的源码有没有对其进行利用。这里仅仅做了参数定义,做了规定,告诉解析器的开发者可能有这些参数
   * 【】配置项目有:
   * "sourceType": "module",    // 指定JS代码来源的类型,script(script标签引入?) | module(es6的module模块),默认为script。为什么vue的会使用script呢?因为vue是通过babel-loader编译的,而babel编译后的代码就是script方式
   * "ecmaVersion": 6,          // 支持的ES语法版本,默认为5。注意只是语法,不包括ES的全局变量。全局变量需要在env选项中进行定义
   * "ecmaFeatures": {          // Features是特征的意思,这里用于指定要使用其他那些语言对象
       "experimentalObjectRestSpread": true,  //启用对对象的扩展
       "jsx": true,                           //启用jsx语法
       "globalReturn":true,                   //允许return在全局使用
       "impliedStrict":true                   //启用严格校验模式
     }
   */
  parserOptions: {
    /**
     * 这里出现 parser 的原因
     * 【】首先明确一点,官方说明中,parserOptions的配置参数是不包括 parser 的
     * 【】这里的写 parser 是 eslint-plugin-vue 的要求,是 eslint-plugin-vue 的自定义参数
     * 【】根据官方文档,eslint-plugin-vue 插件依赖 「vue-eslint-parser」解析器。「vue-eslint-parser」解析器,只解析 .vue 中html部分的内容,不会检测<script>中的JS内容。
     * 【】由于解析器只有一个,用了「vue-eslint-parser」就不能用「babel-eslint」。所以「vue-eslint-parser」的做法是,在解析器选项中,再传入一个解析器选项parser。从而在内部处理「babel-eslint」,检测<script>中的js代码
     * 【】所以这里出现了 parser
     * 【】相关文档地址,https://vuejs.github.io/eslint-plugin-vue/user-guide/#usage
     */
    parser: 'babel-eslint',
  },


  /**
   * 运行环境
   *  http://eslint.cn/docs/user-guide/configuring#specifying-environments
   * 【】一个环境定义了一组预定义的全局变量
   * 【】获得了特定环境的全局定义,就不会认为是开发定义的,跳过对其的定义检测。否则会被认为改变量未定义
   * 【】常见的运行环境有以下这些,更多的可查看官网
   *  browser - 浏览器环境中的全局变量。
   *  node - Node.js 全局变量和 Node.js 作用域。
   *  es6 - 启用除了 modules 以外的所有 ECMAScript 6 特性(该选项会自动设置 ecmaVersion 解析器选项为 6)。
   *  amd - 将 require() 和 define() 定义为像 amd 一样的全局变量。
   *  commonjs - CommonJS 全局变量和 CommonJS 作用域 (用于 Browserify/WebPack 打包的只在浏览器中运行的代码)。
   *  jquery - jQuery 全局变量。
   *  mongo - MongoDB 全局变量。
   *  worker - Web Workers 全局变量。
   *  serviceworker - Service Worker 全局变量。
   */
  env: {
    browser: true, // 浏览器环境
  },


  /**
   * 全局变量
   * http://eslint.cn/docs/user-guide/configuring#specifying-globals
   * 【】定义额外的全局,开发者自定义的全局变量,让其跳过no-undef 规则
   * 【】key值就是额外添加的全局变量
   * 【】value值用于标识该变量能否被重写,类似于const的作用。true为允许变量被重写
   * 【】注意:要启用no-global-assign规则来禁止对只读的全局变量进行修改。
   */
  globals: {
    // gTool: true, // 例如定义gTool这个全局变量,且这个变量可以被重写
  },


  /**
   * 插件
   * http://eslint.cn/docs/user-guide/configuring#configuring-plugins
   * 【】插件同样需要在node_module中下载
   * 【】注意插件名忽略了「eslint-plugin-」前缀,所以在package.json中,对应的项目名是「eslint-plugin-vue」
   * 【】插件的作用类似于解析器,用以扩展解析器的功能,用于检测非常规的js代码。也可能会新增一些特定的规则。
   * 【】如 eslint-plugin-vue,是为了帮助我们检测.vue文件中 <template> 和 <script> 中的js代码
   */
  plugins: ['vue'],


  /**
   * 规则继承
   * http://eslint.cn/docs/user-guide/configuring#extending-configuration-files
   *【】可继承的方式有以下几种
   *【】eslint内置推荐规则,就只有一个,即「eslint:recommended」
   *【】可共享的配置, 是一个 npm 包,它输出一个配置对象。即通过npm安装到node_module中
   *   可共享的配置可以省略包名的前缀 eslint-config-,即实际设置安装的包名是 eslint-config-airbnb-base
   *【】从插件中获取的规则,书写规则为 「plugin:插件包名/配置名」,其中插件报名也是可以忽略「eslint-plugin-」前缀。如'plugin:vue/essential'
   *【】从配置文件中继承,即继承另外的一个配置文件,如'./node_modules/coding-standard/eslintDefaults.js'
   */
  extends: [
    /**
     * vue 的额外添加的规则是 v-if, v-else 等指令检测
     */
    'plugin:vue/essential', // 额外添加的规则可查看 https://vuejs.github.io/eslint-plugin-vue/rules/
    /**
     * 「airbnb,爱彼迎」
     * 【】有两种eslint规范,一种是自带了react插件的「eslint-config-airbnb」,一种是基础款「eslint-config-airbnb-base」,
     * 【】airbnb-base 包括了ES6的语法检测,需要依赖 「eslint-plugin-import」
     * 【】所以在使用airbnb-base时,需要用npm额外下载 eslint-plugin-import
     * 【】所以eslint实际上已经因为 airbnb-base 基础配置项目,添加上了 eslint-plugin-import 插件配置
     * 【】所以在setting和rules里,都有 'import/xxx' 项目,这里修改的就是 eslint-plugin-import 配置
     */
    // 'airbnb-base',
  ],


  /**
   * 规则共享参数
   * http://eslint.cn/docs/user-guide/configuring#adding-shared-settings
   * 【】提供给具体规则项,每个参数值,每个规则项都会被注入该变量,但对应规则而言,有没有用,就看各个规则的设置了,就好比 parserOptions,解析器用不用它就不知道了。这里只是提供这个方法
   * 【】不用怀疑,经源码验证,这就是传递给每个规则项的,会当做参数传递过去,但用不用,就是具体规则的事情
   */
  settings: {
    /**
     *
     * 注意,「import/resolver」并不是eslint规则项,与rules中的「import/extensions」不同。它不是规则项
     * 这里只是一个参数名,叫「import/resolver」,会传递给每个规则项。
     * settings并没有具体的书写规则,「import/」只是import模块自己起的名字,原则上,它直接命名为「resolver」也可以,加上「import」只是为了更好地区分。不是强制设置的。
     * 因为「import」插件很多规则项都用的这个配置项,所以并没有通过rules设置,而是通过settings共享
     * 具体使用方法可参考https://github.com/benmosher/eslint-plugin-import
     */
    'import/resolver': {
      /**
       * 这里传入webpack并不是import插件能识别webpack,而且通过npm安装了「eslint-import-resolver-webpack」,
       * 「import」插件通过「eslint-import-resolver-」+「webpack」找到该插件并使用,就能解析webpack配置项。使用里面的参数。
       * 主要是使用以下这些参数,共享给import规则,让其正确识别import路径
       * extensions: ['.js', '.vue', '.json'],
       * alias: {
       *  'vue$': 'vue/dist/vue.esm.js',
       *  '@': resolve('src'),
       *  'static': resolve('static')
       * }
       */
      webpack: {
        config: 'build/webpack.base.conf.js'
      }
    }
  },

  /**
   * 针对特定文件的配置
   * 【】可以通过overrides对特定文件进行特定的eslint检测
   * 【】特定文件的路径书写使用Glob格式,一个类似正则的路径规则,可以匹配不同的文件
   * 【】配置几乎与 ESLint 的其他配置相同。覆盖块可以包含常规配置中的除了 extends、overrides 和 root 之外的其他任何有效配置选项,
   */
  // overrides: [
  //   {
  //     'files': ['bin/*.js', 'lib/*.js'],
  //     'excludedFiles': '*.test.js',
  //     'rules': {
  //       'quotes': [2, 'single']
  //     }
  //   }
  // ],

  /**
   * 自定义规则
   * http://eslint.cn/docs/user-guide/configuring#configuring-rules
   * 【】基本使用方式
   *  "off" 或者0 关闭规则
   *  "warn" 或者1 将规则打开为警告(不影响退出代码)
   *  "error" 或者2 将规则打开为错误(触发时退出代码为1)
   *  如:'no-restricted-syntax': 0, // 表示关闭该规则
   * 【】如果某项规则,有额外的选项,可以通过数组进行传递,而数组的第一位必须是错误级别。如0,1,2
   *  如 'semi': ['error', 'never'], never就是额外的配置项
   */
  rules: {
    /**
     * 具体规则
     * 【】具体的规则太多,就不做介绍了,有兴趣的同学可以上eslint官网查
     * 【】注意 xxx/aaa 这些规则是 xxx 插件自定的规则,在eslint官网是查不到的。需要到相应的插件官网中查阅
     * 【】如 import/extensions,这是「eslint-plugin-import」自定义的规则,需要到其官网查看 https://github.com/benmosher/eslint-plugin-import
     */
    /**
     * 逻辑错误及最佳实践的规则
     */
    'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, // 打包时禁止debugger
    'no-console': process.env.NODE_ENV === 'production' ? 2 : 0, // 打包时禁止console
    'no-alert': process.env.NODE_ENV === 'production' ? 2 : 0, // 打包时禁止console
    "for-direction": 2, // 禁止for无限循环
    "no-compare-neg-zero": 2, // 禁止与-0进行比较
    'no-cond-assign': 2, // 禁止条件语句中出现赋值语句
    "no-control-regex": 2, // 在 ASCII 中,0-31 范围内的控制字符是特殊的、不可见的字符。这些字符很少被用在 JavaScript 字符串中,所以一个正则表达式如果包含这些字符的,很有可能一个错误。
    "no-dupe-args": 2, // 禁止在函数定义或表达中出现重名参数
    "no-dupe-keys": 2, // 禁止在对象字面量中出现重复的键
    "no-duplicate-case": 2, // 禁止重复 case 标签
    "no-empty": 2, // 禁止空块语句
    "no-empty-character-class": 2, // 禁止在正则表达式中出现空字符集
    "no-ex-assign": 2, // 禁止对 catch 子句中的异常重新赋值。因为catch出来的都是错误信息,不需要重新赋值
    "no-extra-boolean-cast": 2, // 禁止不必要的布尔类型转换,如 !!true
    "no-extra-semi": 2, // 禁用不必要的分号
    "no-inner-declarations": 2, // ??? 禁止在嵌套的语句块中出现变量
    "no-regex-spaces": 2, // 禁止正则表达式字面量中出现多个空格
    "no-obj-calls": 2, // 禁止将全局对象当作函数进行调用
    "no-prototype-builtins": 2, // ??? 禁止直接在对象实例上调用 Object.prototype 的一些方法。
    "no-template-curly-in-string": 2, // 禁止在常规字符串中出现模板字面量占位符语法
    "semi": [2, 'never'], // ??? 强制是否使用分号。
    "no-unexpected-multiline": 2, // 禁止使用令人困惑的多行表达式
    "no-unreachable": 2, // 禁止在 return、throw、continue 和 break 语句后出现不可达代码
    "use-isnan": 2, // 要求调用 isNaN()检查 NaN
    "no-unsafe-negation": 2, // 禁止对关系运算符的左操作数使用否定操作符
    "valid-jsdoc": 2, // 强制使用有效的 JSDoc 注释
    "valid-typeof": 2, // 强制 typeof 表达式与有效的字符串进行比较
    "array-callback-return": 2, // 强制数组方法的回调函数中有 return 语句
    "block-scoped-var": 2, // 把 var 语句看作是在块级作用域范围之内
    "complexity": [1, 6], // 添加复杂度
    "curly": 2, // ??? 要求遵循大括号约定
    "default-case": 1, // 要求 Switch 语句中有 Default 分支
    "dot-location": [2, 'property'], // 强制在点号之前换行
    "dot-notation": 2, // 点号和字面量,优先使用点号
    "eqeqeq": [2, 'smart'], // ??? 要求使用 === 和 !==
    "guard-for-in": 2, // ??? 需要约束 for-in
    "no-caller": 2, // 禁用 caller 或 callee
    "no-empty-function": 2, // 禁止出现空函数
    "no-empty-pattern": 2, // 禁止使用空解构模式
    "no-eval": 2, // 禁用 eval()
    "no-global-assign": 2, // 禁止对原生对象或只读的全局对象进行赋值
    "no-floating-decimal": 2, // ?? 禁止浮点小数
    "no-fallthrough": 2, // 禁止 case 语句落空
    "no-labels": 2, // 禁用标签语句
    "no-extra-label": 2, // 禁用不必要的标签
    "no-extra-bind": 2, // 禁止不必要的函数绑定
    "no-iterator": 2, // 禁用迭代器
    "no-lone-blocks": 2, // 禁用不必要的嵌套块
    "no-loop-func": 2, // 禁止循环中存在函数
    "no-magic-numbers": [2, {
      ignoreArrayIndexes: true,
      ignore: [-1, 0, 1, 2],
    }], // 禁止使用魔术数字,魔术数字是在代码中多次出现的没有明确含义的数字。它最好由命名常量取代。
    "no-multi-spaces": 2, // 禁止出现多个空格
    "no-multi-str": 2, // 禁止多行字符串
    "no-new": 2, // 禁止在不保存实例的情况下使用new
    "no-new-func": 2, // 禁用Function构造函数
    "no-new-wrappers": 2, // 禁止原始包装实例
    "no-octal": 2, // 禁用八进制字面量
    "no-octal-escape": 2, // 禁止在字符串字面量中使用八进制转义序列
    "no-param-reassign": 2, // ??? 禁止对函数参数再赋值
    "no-proto": 2, // 禁用__proto__,改用 getPrototypeOf 方法替代 __proto__。
    "no-redeclare": 2, // 禁止重新声明变量
    "no-return-assign": 2, // 禁止在返回语句中赋值
    "no-return-await": 2, // 禁用不必要的 return await
    "no-script-url": 2, // 禁用 Script URL
    "no-self-assign": 2, // 禁止自身赋值
    "no-sequences": 2, // ??? 不允许使用逗号操作符
    "no-throw-literal": 2, // 限制可以被抛出的异常
    "no-unmodified-loop-condition": 2, // 禁用一成不变的循环条件
    "no-useless-call": 2, // 禁用不必要的 .call() 和 .apply()
    "no-useless-concat": 2, // 禁止没有必要的字符拼接
    "no-useless-escape": 2, // 禁用不必要的转义
    "no-useless-return": 2, // 禁止多余的 return 语句
    "no-void": 2, // 禁止使用void操作符
    "no-with": 2, // 禁用 with 语句
    "prefer-promise-reject-errors": 1, // ??? 要求使用 Error 对象作为 Promise 拒绝的原因
    "radix": 1, // 要求必须有基数
    "require-await": 2, // 禁止使用不带 await 表达式的 async 函数
    "vars-on-top": 2, // 要求将变量声明放在它们作用域的顶部
    "wrap-iife": [2, 'inside'], // 需要把立即执行的函数包裹起来
    "strict": [2, 'global'], // 要求或禁止使用严格模式指令
    /**
     * 变量相关的规则
     */
    "init-declarations": 2, // ??? 强制或禁止变量声明语句中初始化
    "no-delete-var": 2, // 禁止删除变量
    "no-shadow": 2, // 禁止变量声明覆盖外层作用域的变量
    "no-shadow-restricted-names": 2, // 关键字不能被遮蔽
    "no-undef": 2, // 禁用未声明的变量
    "no-unused-vars": 1, // ??? 禁止未使用过的变量
    "no-use-before-define": 2, // 禁止定义前使用
    // 代码风格
    "array-bracket-newline": [2, 'consistent'], // 在数组开括号后和闭括号前强制换行
    "array-bracket-spacing": 2, // 强制在括号内前后使用空格
    "array-element-newline": [2, { multiline: true }], // ??? 强制数组元素间出现换行
    "block-spacing": 2, // 强制在代码块中开括号前和闭括号后有空格
    "brace-style": 2, // 大括号风格要求
    "camelcase": 2, // 要求使用骆驼拼写法
    "comma-dangle": [2, 'always-multiline'], // 要求或禁止使用拖尾逗号
    "comma-spacing": 2, // 强制在逗号周围使用空格
    "comma-style": 2, // 逗号风格
    "computed-property-spacing": 2, // 禁止或强制在计算属性中使用空格
    "consistent-this": [2, 'self'], // ??? 要求一致的 This
    "eol-last": [1, 'always'], // ??? 要求或禁止文件末尾保留一行空行
    "func-call-spacing": 2, // 要求或禁止在函数标识符和其调用之间有空格
    "func-style": [2, 'declaration'], // ??? 强制 function 声明或表达式的一致性
    "function-paren-newline": [1, 'multiline'], // 强制在函数括号内使用一致的换行
    "indent": [2, 2], // 强制使用一致的缩进
    "jsx-quotes": 2, // 强制在 JSX 属性中一致地使用双引号或单引号
    "key-spacing": 2, // 强制在对象字面量的键和值之间使用一致的空格
    "keyword-spacing": 2, // 强制关键字周围空格的一致性
    "linebreak-style": 2, // 强制使用一致的换行符风格,用\n,不用\r\n
    "lines-around-comment": 2, // 强制注释周围有空行
    "lines-between-class-members": 2, // 要求在类成员之间出现空行
    "max-depth": 2, // 强制块语句的最大可嵌套深度
    "max-len": [2, { // 强制行的最大长度
      "code": 100,
      "tabWidth": 4,
      "ignoreUrls": true,
      "ignoreTrailingComments": true,
      "ignoreTemplateLiterals": true,
    }], //
    "max-lines": [2, 1000], // ??? 强制文件的最大行数
    "max-nested-callbacks": [2, 5], // 强制回调函数最大嵌套深度
    "max-statements-per-line": 2, // 强制每一行中所允许的最大语句数量
    "multiline-comment-style": 1, // 强制对多行注释使用特定风格
    "new-cap": 2, // 要求构造函数首字母大写
    "new-parens": 2, // 要求调用无参构造函数时带括号
    "newline-per-chained-call": 2, // 要求方法链中每个调用都有一个换行符
    "no-bitwise": 2, // 禁止使用按位操作符
    "no-inline-comments": 0, // ??? 禁止使用内联注释
    "no-lonely-if": 2, // 禁止 if 语句作为唯一语句出现在 else 语句块中
    "no-mixed-spaces-and-tabs": 2, // 禁止使用 空格 和 tab 混合缩进
    "no-multiple-empty-lines": 1, // ??? 不允许多个空行
    "no-negated-condition": 2, // 禁用否定表达式
    "no-nested-ternary": 2, // 禁止使用嵌套的三元表达式
    "no-new-object": 2, // 禁止使用 Object 构造函数
    "no-trailing-spaces": 2, // 禁用行尾空白
    "no-underscore-dangle": 2, // 禁止标识符中有悬空下划线
    "quotes": [2, 'single'], // 强制使用一致的单引号
    "quote-props": [2, 'as-needed'], // ??? 要求对象字面量属性名称使用引号
    "operator-linebreak": [2, 'before'], // 强制操作符使用一致的换行符风格
    "one-var": [2, 'never'], // ??? 强制函数中的变量在一起声明或分开声明
    "object-property-newline": 1, // ??? 强制将对象的属性放在不同的行上
    "object-curly-spacing": [2, 'always'], // 强制在花括号中使用一致的空格
    "object-curly-newline": [1, { // ??? 对象属性换行
      multiline: true,
    }], //
    "no-whitespace-before-property": 2, // 禁止属性前有空白
    "no-unneeded-ternary": 2, // 禁止可以表达为更简单结构的三元操作符
    "semi-spacing": 2, // 强制分号前后有空格
    "semi-style": 2, // 分号风格
    "space-before-blocks": [2, 'always'], // 禁止语句块之前的空格
    "space-before-function-paren": [2, 'never'], // 禁止函数圆括号之前有一个空格
    "space-in-parens": 2, // 禁止或强制圆括号内的空格
    "space-infix-ops": 2, // 要求中缀操作符周围有空格
    "space-unary-ops": 2, // 禁止在一元操作符之前或之后存在空格
    "spaced-comment": 2, // 要求在注释前有空白
    "switch-colon-spacing": 2, // 强制在 switch 的冒号左右有空格
    "template-tag-spacing": 2, // 要求在模板标记和它们的字面量之间有空格
    /**
     * ES6相关规则
     */
    "arrow-parens": [2, 'as-needed'], // 要求箭头函数的参数使用圆括号
    "arrow-body-style": 2, // 要求箭头函数体使用大括号
    "arrow-spacing": 2, // 要求箭头函数的箭头之前或之后有空格
    "generator-star-spacing": 2, // ??? 强制 generator 函数中 * 号周围有空格
    "no-class-assign": 2, // 不允许修改类声明的变量
    "no-confusing-arrow": 2, // 禁止在可能与比较操作符相混淆的地方使用箭头函数
    "no-const-assign": 2, // 不允许改变用const声明的变量
    "no-dupe-class-members": 2, // 不允许类成员中有重复的名称
    "no-duplicate-imports": 2, // 禁止重复导入
    "no-new-symbol": 0, // 禁止 Symbol 操作符和 new 一起使用lines-between
    "no-useless-computed-key": 2, // 禁止在对象中使用不必要的计算属性
    "no-useless-constructor": 2, // 禁用不必要的构造函数
    "no-useless-rename": 2, // 禁止在 import 和 export 和解构赋值时将引用重命名为相同的名字
    "no-var": 2, // 要求使用 let 或 const 而不是 var
    "object-shorthand": 2, // 要求对象字面量简写语法
    "prefer-arrow-callback": 2, // 要求使用箭头函数作为回调
    "prefer-const": 1, // ??? 建议使用const
    "prefer-destructuring": [2, { // 优先使用数组和对象解构
      "array": false,
      "object": true
    }],
    "prefer-rest-params": 2, // 使用剩余参数代替 arguments
    "prefer-spread": 2, // 建议使用扩展运算符而非.apply()
    "prefer-template": 2, // 建议使用模板而非字符串连接
    "require-yield": 2, // 禁用函数内没有yield的 generator 函数
    "rest-spread-spacing": 2, // 强制剩余和扩展运算符及其表达式之间有空格
    "template-curly-spacing": 2, // 强制模板字符串中空格的使用
    "sort-imports": [0, { // ??? import 排序 问题是要以字母排序
      ignoreCase: true,
      ignoreMemberSort: true,
      memberSyntaxSortOrder: ['all', 'single', 'multiple', 'none']
    }], //
  }
};

原文连接:https://segmentfault.com/a/1190000017461203

webpack-yalc使用

1.在你的组件库中

1.全局安装

npm install -g yalc
npm run build

yalc publish

在你的使用库中

yalc add @xin/xin-statistic

然后会发现

image
image

调试

方案一:每次修改完 build下 在push下

    "yalc": "npm run build && yalc push"

方案二:使用组件直接引入源码

import { echartsService } from '@xin/xin-statistic/src/statistic/echarts/index';

每次修改完只需要:yalc push 即可

关闭调试

yalc remove --all

Shell-命令的应用

npm install -g yarn
npm run yarn
echo "hi-enterprise-platform依赖安装完成"
cd packages/backend
npm run yarn
echo "backend依赖安装完成"
cd ../old-backend
npm run yarn
echo "old-backend依赖安装完成"
cd ../../../hi-enterprise-platform
node scripts/dev/setup.js
echo "一键初始化完成,请运行npm run start"

在pagejson中

     "setup": "sh scripts/dev/setup.sh",

image

Pagejson- ^,~的区别

举个栗子

"devDependencies": {
    "antd": "^3.1.4",
    "babel-plugin-import": "~1.1.0",
    "classnames": "2.2.5",
    "qs": "^6.3.0",
    "robe-ajax": "^1.0.1",
    "expect": "^1.20.2",
    "js-cookie": "^2.1.3",

 .......
}

(1)指定版本:比如"classnames": "2.2.5",表示安装2.2.5的版本

(2)波浪号~+指定版本:比如 "babel-plugin-import": "~1.1.0",表示安装1.1.x的最新版本(不低于1.1.0),但是不安装1.2.x,也就是说安装时不改变大版本号和次要版本号

(3)^+指定版本:比如 "antd": "^3.1.4",,表示安装3.1.4及以上的版本,但是不安装4.0.0,也就是说安装时不改变大版本号。

Linux-常用命令

1.创建文件夹

mkdir -p xxxxx

2.复制文件到某目录下

cp -rf packages/backend/dist/* output/ge //复制 packages/backend/dist下所有内容到 output/ge目录下

3.压缩文件

cd output

zip -r output.zip .

4.强制递归删除文件

rm -rf

5.递归复制

cp -rf

webpack-项目性能测试

第一步:webpacl配置中 引入插件

    if (process.env.npm_config_report) {
      config
        .plugin('webpack-bundle-analyzer')
        .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
    }

第二步:package.json中加命令

    "analyz": "npm_config_report=true npm run build",

第三步:运行命令

npm run analyz

篇外配置-Hosts文件

hosts 是什么

当用户在浏览器中输入一个需要登录的网址时,系统会首先自动从Hosts文件中寻找对应的IP地址,一旦找到,系统会立即打开对应网页,如果没有找到,则系统会再将网址提交DNS域名解析服务器进行IP地址的解析。

域名对应错误 IP 地址,那么就会起到屏蔽的作用。比如:127.0.0.1 www.zuohaotu.com

image

spring cloud @FeignClient 多个服务间调用,可以用 IP + 域名 配置到hosts 文件里面,本地启动也可以无感调用其它服务。 比如,你配置的测试环境的 IP + 域名,那么你本地跑项目也可以调测服上面的服务。

GitHub 图片刷不出来。

image

image

image

查询 IP的地址:www.ipaddress.com/

Webpack-npm,yarn,nrm应用

  • npm是安装node时自带的包管理工具。
  • npm包有很多的镜像源,nrm是切换不同的镜像源的工具,切换后还是用npm安装。
  • yarn是facebook公司开发的替代npm的包管理工具,是需要额外安装的,用来解决npm的一些毛病。从工具的使用上理解,yarn与npm是一样的,如果你安装了yarn,那一般都使用yarn,因为它更快更好。

npm

npm install express          # 本地安装
npm install express -g       # 全局安装

yarn

https://yarnpkg.com/zh-Hans/docs/cli/

nrm

 npm install -g nrm
npm ls  列出已安装的包
nrm use local
nrm del
nrm add
nrm test npm//测试源的速度

yarn命令与npm对比

https://classic.yarnpkg.com/zh-Hans/docs/migrating-from-npm

webpack-vite为什么比webpack快

Webpack

image

Webpack 会遍历你的应用程序中的所有文件,并启动一个开发服务器,然后将整个代码渲染到开发环境中。

webpack从一个entry.js文件开始,将其依赖的所有js或者其他assets通过loader打包成一个文件, 随后这个打包后的文件将被从server传递到客户端浏览器运行。

因为这样的处理规则,当保存文件时,整个 JavaScript 包将由 Webpack 重新构建,这就是为什么更改可能需要长达 10 秒才能反映在浏览器中,更新速度会随着应用体积增长而直线下降。

Vite

image

Vite 的工作方式不同,它不会遍历整个应用程序,Vite 只是转换当时正在使用的文件/模块。

Vite的核心理念:非捆绑开发构建

Vite 的核心**:浏览器请求它时,使用 ES 模块转换并提供一段应用程序代码。

开始开发构建时,Vite首先将JavaScript 模块分为两类:依赖模块和源码模块。

依赖项模块是第三方依赖的代码,从node_modules文件夹中导入的JavaScript 模块。这些模块将使用esbuild进行处理和捆绑,esbuild是一个用 Go 编写的 JavaScript 打包工具,执行速度比 Webpack 快 10-100 倍。

源码模块是源代码,即业务代码,通常涉及特定库的扩展,如:.jsx、.vue、.scss文件。

它使用基于路由的代码拆分来了解代码的哪些部分实际需要加载,因此,它不必重新打包所有内容。

它还使用现代浏览器中的原生 ES 模块支持来交付代码,这让浏览器可以在开发中承担打包工作。

在生产方面,虽然现在所有主流浏览器都支持原生 ES 模块,但它实现了诸如 tree-shaking、延迟加载和通用块拆分等性能优化技术,仍然比非打包应用程序带来更好的整体性能。出于这个原因,Vite附带了一个预先配置的build命令,该命令使用Rollup打包来打包和实现各种性能优化。

Webpack 这样的基于打包器的工作流必须在单个浏览器请求之前处理整个 JavaScript 模块,但 Vite 只在单个浏览器请求之前处理依赖模块。这就是为什么 Vite 能够比 Webpack 更快地处理开发构建。
image

Lerna-学习使用

Lerna是优化和管理JS多包项目的利器

Lerna的目录结构

multi-packages/
  package.json
  packages/
    package-1/
      package.json
    package-2/
      package.json

packages文件夹就是用来承载多个项目的目录

lerna项目中最常用到的命令是

lerna bootstrap

lerna publish。
  • lerna bootstrap用于为所有项目安装依赖,类似于npm i/yarn ;
  • lerna publish用于提交对项目的更新。基于以上两点,需要在项目中使用npm和git。

lerna的安装

npm i -g lerna
//或
yarn global add lerna

然后 lerna init --生成packages文件夹和lerna.json文件。并在package.json文件中的devDependencies字段中生成lerna对应的依赖信息。

固定模式

固定模式是默认的模式,版本号使用 lerna.json 文件中的 version 属性。执行 lerna publish 时,如果代码有更新,会自动更新此版本号的值。

独立模式

独立模式,允许维护人员独立的增加修改每个包的版本,每次发布,所有更改的包都会提示输入指定版本号。

使用方式:

lerna init --independent

修改 lerna.json 中的 version 值为 independent ,可将固定模式改为独立模式运行。

相关文档:https://www.codercto.com/a/84794.html

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.