IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> [万字逐步详解]使用 webpack-dev-server + ESLint 配置 vue 项目的开发环境 -> 正文阅读

[JavaScript知识库][万字逐步详解]使用 webpack-dev-server + ESLint 配置 vue 项目的开发环境

[万字逐步详解]使用 webpack-dev-server + ESLint 配置 vue 项目的开发环境

在上一篇 [万字逐步详解]使用 webpack 打包 vue 项目(基础生产环境) 中,一步一步的完成了基础生产环境的配置,这里就是对开发环境的配置进行实现了。

本次会使用到的依赖只有 webpack-dev-server 和 ESLint 相关的插件,这里会用 webpack-dev-server 去进行开发环境的配置,并且实现以下功能:

  • 开发环境的配置

  • Source Map 的添加

  • HRM 的开启

    HRM 的开启是为了能够更加有效的进行开发,只更新被修改的模块,而不会将整个项目重新打包

  • ESLint 的设置

使用 webpack-dev-server 开发服务器的部署

目前为止,我本地的热部署使用的是 VSCode 提供的插件:Live Server。但是,并不是所有的开发团队成员都会使用同样的开发软件,同样,也不能保证所有的成员都有一样的插件。因此,开发一个具有相同功能的服务器就是一件必须的事情了。

这里会使用 webpack-dev-server
去解决这个问题,webpack-dev-server 集成了一些自动化的功能,因此可以搞定自动编译、自动监听、自动刷新浏览器的功能。

  1. 下载安装插件

    npm install webpack-dev-server --save-dev
    
  2. 修改配置

    webpack-dev-server 会提供一个 dev-server 的 cli 程序,通过这个程序就可以开启一个服务器。这里会通过将这个命令写到 package.json 里面的 scripts 去节省一些事儿:

    {
      "scripts": {
        "serve": "webpack serve --mode=development --open"
      }
    }
    

    其他的配置属性不变,只新增一个 serve 命令即可。

    现在开始配置 webpack.config.js,注意,为了提升效率, webpack-dev-server 是将文件保存在缓存中,而不会直接在磁盘中进行重写。

    在配置中其实可以将 publicPath: "./" 这一行注释掉,一来其实并不影响 production 的打包,二来没有办法正确的将所有的数据缓存起来,会影响 dev server 的情况。

    具体的配置如下:

    module.exports = {
      // 这个还蛮重要的,不然不知道为什么热更新会失败
      target: 'web',
      // 省略其他配置
      devServer: {
        // 指定端口
        port: 9000,
        // 命令行中会显示打包的进度
        progress: true,
        // 开启热更新
        hot: true,
        // 是个很有趣的特性
        historyApiFallback: true,
        // 添加静态资源的引用,可以用数组
        // 这样原本没有被打包进去的内容也可以正确被引用
        contentBase: path.join(__dirname, 'public'),
      },
      // 省略其他配置
    };
    

    在配置完了 contentBase 之后,也就代表着可以在开发环境中取消使用 copy-plugin,这样在针对比较大的文件的时候——尤其是有些图片确实会比较大,就能够省去不少的时间。

    historyApiFallback 是一个还挺有趣的特性,它主要是提供了一个路径让服务器去调用,官方文档是这样说的:

    module.exports = {
      //...
      devServer: {
        historyApiFallback: {
          rewrites: [
            { from: /^\/$/, to: '/views/landing.html' },
            { from: /^\/subpage/, to: '/views/subpage.html' },
            { from: /./, to: '/views/404.html' },
          ],
        },
      },
    };
    

    也就是说,当访问的路径与指定的路径 match 的时候,就会跳转到 to 中指定的页面。

  3. 关于 html-webpack-plugin

    这个之前在做 production 环境配置的时候就已经折腾好了,这里不多赘述,这部分在 [万字逐步详解]使用 webpack 打包 vue 项目(基础生产环境) 已经有详细的配置说明了。

  4. 修改点什么试试看结果

    从命令行就能看到,保存过后就会重新编译,这样热更新就完成了:

    最终效果:

添加 source map

添加 source map 是为了能够方便 debug,现在打开 chrome 中的 source,显示的代码是不可读的:

如果是开发公共组件,在有些时候,直接提供打包好的 bundle 对其他的使用这个开源库的用户来说,就会有阅读困难的问题。所以,这里会加上添加 source map 的功能。

配置是内置的,只需要添加一行新的配置即可:

module.exports = {
  // 其他不变
  devtool: 'eval-cheap-module-source-map',
};

长试运行一下 npm run build 之后,就会看到打包出了一个新的文件:

在使用 Live Server 启用了一个服务器后,再去打开打包后的 index.html,会有下面这样的提示跳出来:

这就说明系统已经能够找到对应的源码,报错就可以直接定位到源码报错的地方。

选择 cheap-module-source-map 的原因很简单,它会将 webpack 打包好的模块按照 module 还原成源码,并且能够准确定位到报错的行。在正常的情况下,为了保证代码的可读性,每行代码在 80-120 个字符范围内的情况下,定位到行就已经够了。

另外,对于 React/Vue 来说,原生的 JavaScript 和二者的语法糖差异较大,很难从编译过后的 JavaScript 直接在脑中转换成对应框架的代码,所以这也是需要使用源码的原因。同理,在生产环境就应该使用 nosources/none 的选项,这样别人就比较难从编译过后的 JavaScript 了解到源码。

下面是来自 webpack-Devtool 官网上列举的差别:

devtoolperformanceproductionqualitycomment
(none)build: fastest

rebuild: fastest
yesbundleRecommended choice for production builds with maximum performance.
evalbuild: fast

rebuild: fastest
nogeneratedRecommended choice for development builds with maximum performance.
eval-cheap-source-mapbuild: ok

rebuild: fast
notransformedTradeoff choice for development builds.
eval-cheap-module-source-mapbuild: slow

rebuild: fast
nooriginal linesTradeoff choice for development builds.
eval-source-mapbuild: slowest

rebuild: ok
nooriginalRecommended choice for development builds with high quality SourceMaps.
cheap-source-mapbuild: ok

rebuild: slow
notransformed
cheap-module-source-mapbuild: slow

rebuild: slow
nooriginal lines
source-mapbuild: slowest

rebuild: slowest
yesoriginalRecommended choice for production builds with high quality SourceMaps.
inline-cheap-source-mapbuild: ok

rebuild: slow
notransformed
inline-cheap-module-source-mapbuild: slow

rebuild: slow
nooriginal lines
inline-source-mapbuild: slowest

rebuild: slowest
nooriginalPossible choice when publishing a single file
eval-nosources-cheap-source-mapbuild: ok

rebuild: fast
notransformedsource code not included
eval-nosources-cheap-module-source-mapbuild: slow

rebuild: fast
nooriginal linessource code not included
eval-nosources-source-mapbuild: slowest

rebuild: ok
nooriginalsource code not included
inline-nosources-cheap-source-mapbuild: ok

rebuild: slow
notransformedsource code not included
inline-nosources-cheap-module-source-mapbuild: slow

rebuild: slow
nooriginal linessource code not included
inline-nosources-source-mapbuild: slowest

rebuild: slowest
nooriginalsource code not included
nosources-cheap-source-mapbuild: ok

rebuild: slow
notransformedsource code not included
nosources-cheap-module-source-mapbuild: slow

rebuild: slow
nooriginal linessource code not included
nosources-source-mapbuild: slowest

rebuild: slowest
yesoriginalsource code not included
hidden-nosources-cheap-source-mapbuild: ok

rebuild: slow
notransformedno reference, source code not included
hidden-nosources-cheap-module-source-mapbuild: slow

rebuild: slow
nooriginal linesno reference, source code not included
hidden-nosources-source-mapbuild: slowest

rebuild: slowest
yesoriginalno reference, source code not included
hidden-cheap-source-mapbuild: ok

rebuild: slow
notransformedno reference
hidden-cheap-module-source-mapbuild: slow

rebuild: slow
nooriginal linesno reference
hidden-source-mapbuild: slowest

rebuild: slowest
yesoriginalno reference. Possible choice when using SourceMap only for error reporting purposes.

基本上来说,webpack 都已经显示了推荐用于不同情况下的不同环境,推荐使用哪种类型的 devtool 了,这里简单描述下:

  • 带有 eval

    将模块代码放到 eval 函数中去执行,从而产生独立的作用域,再通过 source-url 去标注文件的路径

    只有 eval 的情况下,只能定位报错的文件

  • 带有 source-map

    这会将代码转译成转换过的代码,可定位到具体的行和列

  • 带有 cheap-source-map

    这会将代码转译成转换过的代码,代码会定位到行,但是不会定位到列

  • 带有 module-source-map

    会将代码翻译成原生代码,并不会进行转译。即,未经过 loader 转译过后的代码

  • 带有 inline-source-map

    将源码嵌入到 module 代码中去,webpack 推荐,这种情况可能在发布独立一个文件时发生

  • hidden

    开发模式下看不见源码,但是源码会被一起打包

    比较适合用于开源项目

  • nosources

    会显示行列信息,但是不会列出源码

    比较适合用于生产环境

所以说,正常来说我会选择使用 eval-cheap-module-source-map 作为开发环境,而 nosources/none 作为部署环境的代码。

下面是报错结果,我刻意在 Vue.js 中导入了一个不存在的文件:

import HelloWorld from './components/HelloWorld.vue';
// Error组件不存早,下面在源代码中是第10行
import Error from './components/Error.vue';

浏览器中的报错结果如下:

注意最后的 App.vue:formatted:11 这段,已经很好的提示错误所在了。

其实这里是强行刷新后产生的报错结果,出现报错的情况下 webpack 会自动停止热刷新,一直到错误修复为止。相似的错误信息也会出现在开启服务器的终端上。

HRM 的开启

这里使用的是 webpack5,一定要确认版本,v4 和 v5 之间配置的差别似乎不太一样,二者的配置不一定能通用。

HRM,即 Hot Module Replacement,即模块热替换,也就是只编译更新过的模块的功能。

之前的配置,即:

module.exports = {
  // 这一行说明运行环境是类似浏览器的环境
  target: 'web',
  devServer: {
    // 开启热更新
    hot: true,
  },
};

其实已经开启了 HMR 和 Live Reloading:

所以这一步相当于在之前的配置中已经完成了。

验证 HMR 效果

已知目录结构是这样的:

并且依赖关系是:main 引用 App.vue, App.vue 引用 HelloWorld.vue,所以可以分别修改 main.js, App.vue, 和 HelloWorld.vue 去验证重新打包的大小,借此验证 HMR 是否更新成功。

  • 更新 HelloWorld.vue

    assets by path *.js 2.54 MiB
      asset bundle.js 2.53 MiB [emitted] (name: main)
      asset main.598fea34c0d6bb419535.hot-update.js 17 KiB [emitted] [immutable] [hmr] (name: main)
    asset index.html 602 bytes [emitted]
    asset main.598fea34c0d6bb419535.hot-update.json 28 bytes [emitted] [immutable] [hmr]
    Entrypoint main 2.54 MiB = bundle.js 2.53 MiB main.598fea34c0d6bb419535.hot-update.js 17 KiB
    cached modules 863 KiB [cached] 264 modules
    runtime modules 26.8 KiB 14 modules
    javascript modules 9.46 KiB
    

    这里可以看到两组对比:

    • main.598fea34c0d6bb419535.hot-update.js 17 KiB

      热更新的部分的大小是 17KiB

    • cached modules 863 KiB [cached] 264 modules

      缓存的大小是 863Kib

    接下来还原 Helloworld.vue,保存后,再更新 App.Vue

  • 更新 App.Vue

    assets by path *.js 2.54 MiB
      asset bundle.js 2.53 MiB [emitted] (name: main)
      asset main.815ce3af01699b267e86.hot-update.js 10.1 KiB [emitted] [immutable] [hmr] (name: main)
    asset index.html 602 bytes [emitted]
    asset main.815ce3af01699b267e86.hot-update.json 28 bytes [emitted] [immutable] [hmr]
    Entrypoint main 2.54 MiB = bundle.js 2.53 MiB main.815ce3af01699b267e86.hot-update.js 10.1 KiB
    cached modules 870 KiB [cached] 264 modules
    
    • main.815ce3af01699b267e86.hot-update.js 10.1 KiB

      热更新的部分的大小是 10.1KiB

      可以看到热更新的代码少了

    • cached modules 870 KiB [cached] 264 modules

      缓存的大小是 870Kib

      可以看到缓存的模块多了

      继续还原后再给 main.js 加个空格

  • 更新 main.js

    assets by path *.js 2.53 MiB
      asset bundle.js 2.53 MiB [emitted] (name: main)
      asset main.fafa37f13c47741d83cd.hot-update.js 2.37 KiB [emitted] [immutable] [hmr] (name: main)
    asset index.html 602 bytes [emitted]
    asset main.fafa37f13c47741d83cd.hot-update.json 28 bytes [emitted] [immutable] [hmr]
    Entrypoint main 2.53 MiB = bundle.js 2.53 MiB main.fafa37f13c47741d83cd.hot-update.js 2.37 KiB
    cached modules 873 KiB [cached] 267 modules
    
    • main.fafa37f13c47741d83cd.hot-update.js 2.37 KiB

      能看出热更新的部分又少了

    • cached modules 873 KiB

      而缓存的模块又多了

这已经可以证明模块热替换的功能已经实现了。

ESLint 设置

在 webpack 中,ESLint 的也是通过 loader 进行实现。理论上来说,在 JavaScript 文件被处理之前,应该通过 ESLint 的 loader 对 JavaScript 源码加上该有的信息。

注*:来自 webpack 官网:

The loader eslint-loader will be deprecated soon, please use this plugin instead.

所以这里会使用对应的插件完成功能。

注 2*:使用 webpack 插件去运行时,ESLint 部分的运行失败,好像并不会影响项目的运行。

  1. 安装插件

    这里也是根据报错信息来的,如果不是 vue 项目,不需要下载 eslint-plugin-vue

    一路上报错……还挺多的

    # 要用 ESLint 的 webpack 插件肯定要先安装 ESLint
    npm install eslint --save-dev
    Usage
    # 安装对应的 webpack 插件
    npm install eslint-webpack-plugin --save-dev
    # 安装对应的 vue 版本
    npm install eslint-plugin-vue --save-dev
    # 又一个报错信息,提示需要 babel-eslint
    npm install babel-eslint --save-dev
    

    这些都安装完了之后,报错终于停止了,可以开始配置工作了。

  2. 配置文件

    这一步还蛮烦的,一点一点来。

    1. 初始化 eslint

      执行命令 npx eslint --init

      C:\assignment\front\lagoufed-e-task\part2\fed-e-task-02-02\code\vue-app-base>npx eslint --init
      ? How would you like to use ESLint? ...
        To check syntax only
      > To check syntax and find problems
        To check syntax, find problems, and enforce code style
      

      第一步会有三个选项,第一个只会找语法错误,第二个会找语法错误和问题代码,如未使用的变量、不存在的变量等,第三个就是加上代码风格的检查,包括行太长,缩进之类的问题。

      这里选择第三个,也检查代码风格

      现在是第二个问题:

      ? What type of modules does your project use? ...
      > JavaScript modules (import/export)
        CommonJS (require/exports)
        None of these
      

      这里使用的时候 vue,不在二者之间,所以选择 None

      然后是第三个问题:

      ? Which framework does your project use? ...
      > React
        Vue.js
        None of these
      

      这里用的是 Vue,就选 Vue 了

      第四个问题:

      ? Does your project use TypeScript? ? No / Yes

      这里没有用 TypeScript,选择 No

      第五个问题:

      ? Where does your code run? ...  (Press <space> to select, <a> to toggle all, <i> to invert selection)
      √ Browser
      √ Node
      

      这里虽然看不清楚,但是 Browser 和 Node 的 √ 的颜色其实不太一样。

      是个网页项目,选择 Browser 即可。

      第六个问题:

      ? How would you like to define a style for your project? ...
      > Use a popular style guide
        Answer questions about your style
        Inspect your JavaScript file(s)
      

      第一个选项就是用主流风格,第二个就是它会提示问题,然后自动生成,最后选项就是根据 JavaScript 文件自动生成。

      我想躺不想努力了,用市面上现成的风格。

      第七个问题:

      ? Which style guide do you want to follow? ...
      > Airbnb: https://github.com/airbnb/javascript
        Standard: https://github.com/standard/standard
        Google: https://github.com/google/eslint-config-google
        XO: https://github.com/xojs/eslint-config-xo
      

      可恶……居然没有 Vue 的选项,那就用 Airbnb 吧(React 项目中用 Airbnb 习惯了)。

      第八个问题:

      ? What format do you want your config file to be in? ...
      > JavaScript
        YAML
        JSON
      

      配置文件的类型,盲选 JavaScript。

      第九个问题:

      Checking peerDependencies of eslint-config-airbnb-base@latest
      The config that you've selected requires the following dependencies:
      
      eslint-plugin-vue@latest eslint-config-airbnb-base@latest eslint@^5.16.0 || ^6.8.0 || ^7.2.0 eslint-plugin-import@^2.22.1
      ? Would you like to install them now with npm? ? No / Yes
      

      问你要不要安装对应的插件……当然……

    2. 修改.eslintrc.js

      module.exports = {
        extends: [
          // 这里原本是essential,改成了recommended
          'plugin:vue/recommended',
          'airbnb-base',
        ],
        rules: {
          // 搞定换行符的问题,windows和unix的换行符不一样,所以这个可能会爆出大量的错误,尤其是开发设备不统一的情况下
          'linebreak-style': [
            'error',
            process.platform === 'win32' ? 'windows' : 'unix',
          ],
          // Disallow self-closing on HTML void elements 的问题
          'vue/html-self-closing': [
            'error',
            {
              html: {
                void: 'always',
                normal: 'never',
                component: 'always',
              },
              svg: 'always',
              math: 'always',
            },
          ],
          // XXX should be on a new line 问题
          'vue/max-attributes-per-line': [
            // 修改警告等级
            'warn',
            {
              // 单行时设置每行的上限为3个
              singleline: 3,
              // 多行的配置
              multiline: {
                // 多行的属性上限
                max: 1,
                // 允许第一行可以设置属性
                allowFirstLine: false,
              },
            },
          ],
          // 修改 unused 和 quotes 的警告等级
          'no-unused-vars': ['warn'],
          quotes: ['warn'],
        },
      };
      
  3. 代码测试

    最后使用 npx run src/App.vue 的运行结果:

    unused var 是我想要看到的结果,single quote 这个引号问题可以搭配 prettier 这种工具去进行自动修正。

    同时使用 npm run serve 也能看到 ESLint 抛出异常,这也可以证明 ESLint 的配置已经成功了。

  4. 对 package.json 的补充

    补充一下 lint 脚本:

    {
      "script": {
        "build": "webpack --config webpack.prod.js",
        "lint": "eslint **/*.vue"
      }
    }
    

    注*:如果直接运行 npm run lint,并且文件中有错误信息的话,npm 会抛出错误异常:

    npm ERR! code ELIFECYCLE
    npm ERR! errno 1
    npm ERR! vue-app-base@0.1.0 lint: `eslint **/*.vue`
    npm ERR! Exit status 1
    npm ERR!
    npm ERR! Failed at the vue-app-base@0.1.0 lint script.
    npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
    

    在 eslint 一个 issue 中也有讨论过这个问题:When running eslint with npm script, npm throws error. #7933,杰伦就是,这件事情是正常的。因为程序运行有异常,ESLint 抛出了一场又被 npm 所捕获,所以最终以 1 退出运行,这就会造成报错。

    试了一下讨论中说可以这么修改:"lint": "eslint app/;exit 0",最终报错,无法使用,唯一成功的就是修改运行时后的脚本,将运行命令改为:npm run lint -s,这样的做法其实是 silent(安静) 报错信息,隐藏报错信息而已。如果个人看的不舒服可以使用后者去解决,不过就说一下,这不代表 ESLint 运行失败——所有的错误异常都显示了,这只是程序的正常处理逻辑。

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-04 21:14:30  更:2021-07-04 21:14:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/26 12:16:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码