第四节:Webpack本地服务器搭建、剖析devServer的HRM热替换和其它配置、resolve模块解析、区分开发/生产环境方案实战

摘要:
1、 Webpack本地服务器设置1.为什么构建本地服务器评测Webpack dev服务器在编译后不会写入任何输出文件,但会将打包的文件保存在内存中。事实上,webpack-dev服务器使用一个名为memfs的库。默认值为false。将其设置为true将打开浏览器。

一. webpack本地服务器搭建

1. 为什么要搭建本地服务器?

 我们之前通过npm run build】,编译相关的代码; 然后需要在浏览器中运行,每次修改修改代码,都需要重新编译运行,很麻烦。我们希望可以做到,文件发生变化时,可以自动的完成 编译 和 展示

第四节:Webpack本地服务器搭建、剖析devServer的HRM热替换和其它配置、resolve模块解析、区分开发/生产环境方案实战第1张

2. watch mode模式

(1). 简介

  在该模式下,webpack依赖图中的所有文件,只要有一个发生了更新,那么代码将重新编译我们不需要手动去运行 npm run build指令了;

(2). 配置

方法1:babel.config.js增加下面配置

module.exports = {
    mode: "development",
    watch:true,     //开启监听
    entry: "./src/main.js"
}

方法2:在package.json中增加下面配置

  "scripts": {
    "build": "webpack --watch"
  },

结果剖析:

  通过【npm run build】打包,运行index.html,这个时候在修改一下代码,自动编译映射。

  上述watch mode,可以监听到文件的变化,但是事实上它本身是没有自动刷新浏览器的功能的: 我们希望在不使用live-server(vs code插件)的情况下,可以具备live reloading(实时重新加载)的功能 ,这个使用就需要用下面的dev-server模式

3. dev-server模式(推荐)

(1). 步骤

 A. 安装loader:npm install webpack-dev-server -D

 B. 修改babel.config.js中的配置,增加target节点 、devServer节点。

// 这里必须通过 commonjs的写法配置,不能写 ES6的写法
const path = require('path');

module.exports = {
    target: "web",
    mode: "development", // 设置模式, development 开发阶段, 会设置development, production 准备打包上线的时候, 设置production(默认)
    entry: "./src/main.js", //入口文件
    output: {
        path: path.resolve(__dirname, "./build"), //打包后存放路径, 必须写绝对路径
        filename: "bundle.js" //打包后的文件名称
    },
    devServer: {
        static: {
            directory: path.join(__dirname, 'public'),
        },                                              //表示从这个文件夹里找打包后没有找到的文件(打包是打src文件夹)
    },
    module: {
   
    },
}

 C. 修改package.json中的配置,script标签中增加serve节点。

  "scripts": {
    "build": "webpack",
    "serve": "webpack serve"
  },

 D. 运行指令【npm run serve】,然后访问 http://localhost:8080/ ,然后F12打开调试器,修改代码,发现页面自动刷新了,输出最新的结果了。

第四节:Webpack本地服务器搭建、剖析devServer的HRM热替换和其它配置、resolve模块解析、区分开发/生产环境方案实战第2张

(2). 剖析 

    webpack-dev-server 在编译之后不会写入到任何输出文件(不会生成build文件夹),而是将 打包后 文件保留在内存中。

 事实上webpack-dev-server使用了一个库叫memfs(memory-fs webpack自己写的) 。

二. dev-server的热替换

1. 简介

第四节:Webpack本地服务器搭建、剖析devServer的HRM热替换和其它配置、resolve模块解析、区分开发/生产环境方案实战第3张

PS:

  特别是当页面有计数器的情况下,HMR更加适合,因为不需要刷新整个页面,计数器就不会被重置。

2. 如何配置

(1). babel.config.js中的配置

devServer: {
        hot: true,
}

(2). 需要动态指定哪个模块需要HMR

hmr.js代码如下:

console.log('hmr11111122333');

导入main.js中(必须先import导入,再配置)

// 测试HMR
import '@js/hmr';
if (module.hot) {
  module.hot.accept("./js/hmr.js", () => {
    console.log("hmr模块发生更新了");
  })
}

(3). 运行结果

第四节:Webpack本地服务器搭建、剖析devServer的HRM热替换和其它配置、resolve模块解析、区分开发/生产环境方案实战第4张

3. HMR的原理

(1). 说明

  vue开发中,我们使用vue-loader,此loader支持vue组件的HMR,提供开箱即用的体验;不需要单独配置module.hot.accept

(2). 原理剖析

第四节:Webpack本地服务器搭建、剖析devServer的HRM热替换和其它配置、resolve模块解析、区分开发/生产环境方案实战第5张

第四节:Webpack本地服务器搭建、剖析devServer的HRM热替换和其它配置、resolve模块解析、区分开发/生产环境方案实战第6张

三. dev-server的其它配置

(更多配置参考官网:https://webpack.js.org/configuration/dev-server/)

1. 基本配置

(1). static→directory:用于设置后打包后寻找静态资源的文件夹

(2). hot:设置为true,开启热替换。

(3). host:设置主机地址,默认值为localhost

(4). port:设置监听的端口,默认情况下是8080

(5). open:是否打开浏览器。 默认值是false,设置为true会打开浏览器。

(6). compress:是否为静态文件开启gzip compression: 默认值是false,可以设置为true;
第四节:Webpack本地服务器搭建、剖析devServer的HRM热替换和其它配置、resolve模块解析、区分开发/生产环境方案实战第7张

分享完整节点:

module.exports = {
    target: "web",
    devServer: {
        static: {
            directory: path.join(__dirname, 'public'), //表示从这个文件夹里找打包后没有找到的文件(打包是打src文件夹)
        },
        hot: true,
        host: "localhost",
        port: 9999,
        open: true,
        compress: true
    },
}

补充几个本地地址的区别:

第四节:Webpack本地服务器搭建、剖析devServer的HRM热替换和其它配置、resolve模块解析、区分开发/生产环境方案实战第8张

2. 代理配置

(1). 简介 

 proxy是我们开发中非常常用的一个配置选项,它的目的设置代理来解决跨域访问的问题:

 A. 比如我们的一个api请求是 http://localhost:8888,但是本地启动服务器的域名是 http://localhost:8000,这个时候发送网络请求就会出现跨域的问题

 B. 那么我们可以将请求先发送到一个代理服务器代理服务器和API服务器没有跨域的问题,就可以解决我们的跨域问题了

PS:在实际开发中,跨域问题通常要配合服务器端一起解决,比如服务器端设置cors等等。

(2). 常用配置  

 target:表示的是代理到的目标地址,比如 /api-hy/moment会被代理到 http://localhost:8888/api-hy/moment;

 pathRewrite:默认情况下,我们的 /api-hy 也会被写入到URL中,如果希望删除,可以使用pathRewrite;

 secure:默认情况下不接收转发到https的服务器上,如果希望支持,可以设置为false;

 changeOrigin:它表示是否更新代理后请求的headers中host地址;

 historyApiFallback是开发中一个非常常见的属性,它主要的作用是解决SPA页面在路由跳转之后,进行页面刷新时,返回404的错误。boolean值:默认是false。如果设置为true,那么在刷新时,返回404错误时,会自动返回 index.html 的内容;object类型的值,可以配置rewrites属性(了解):可以配置from来匹配路径,决定要跳转到哪一个页面;

完整代码: 

devServer: {
        static: {
            directory: path.join(__dirname, 'public'), //表示从这个文件夹里找打包后没有找到的文件(打包是打src文件夹)
        },
        hot: true,
        host: "localhost",
        port: 9999,
        open: true,
        compress: true,
        // 下面是代理相关的配置
        proxy: {
            "/api": {
                target: "http://localhost:8888",
                pathRewrite: {
                    "^/api": ""
                },
                secure: false,
                changeOrigin: true
            }
        }
    },

四. resolve模块解析

1. 背景

 在开发中我们会有各种各样的模块依赖,这些模块可能来自于自己编写的代码,也可能来自第三方库;

 resolve可以帮助webpack从每个 require/import 语句中,找到需要引入到合适的模块代码

 webpack 使用 enhanced-resolve 来解析文件路径;

2. webpack识别的3中路径

(1). 绝对路径

 由于已经获得文件的绝对路径,因此不需要再做进一步解析

(2). 相对路径

 在这种情况下,使用 import 或 require 的资源文件所处的目录,被认为是上下文目录;

 在 import/require 中给定的相对路径会拼接此上下文路径,来生成模块的绝对路径

(3). 模块路径

 在 resolve.modules中指定的所有目录检索模块;

 A. 默认值是 ['node_modules'],所以默认会从node_modules中查找文件; 

 B. 我们可以通过设置别名的方式来替换初识模块路径,后面讲解alias的配置;

3. 区分文件 or 文件夹

(1). 如果是一个文件:

  A. 如果文件具有扩展名,则直接打包文件

  B. 否则,将使用 resolve.extensions选项作为文件扩展名解析(默认情况下,.js/wasm/mjs/json结尾的可以不用写后缀)

(2). 如果是一个文件夹:

  会在文件夹中根据 resolve.mainFiles配置选项中指定的文件顺序查找;

  A. resolve.mainFiles的默认值是 ['index']

  B. 再根据 resolve.extensions来解析扩展名

4. 代码配置(重要)

(1). extensions是解析到文件时自动添加扩展名:

  默认值是 ['.wasm', '.mjs', '.js', '.json'];所以如果我们代码中想要添加加载 .vue 或者 jsx 或者 ts 等文件时,我们必须自己写上扩展名;

(2). 配置别名alias:

  特别是当我们项目的目录结构比较深的时候,或者一个文件的路径可能需要 ../../../这种路径片段;我们可以给某些常见的路径起一个别名;

配置分享

    resolve: {
        extensions: [".js", ".json", ".mjs", ".vue", ".ts", ".jsx", ".tsx"],   //vue ts jsx tsx 是自己添加的后缀
        alias: {
            "@": path.resolve(__dirname, "./src"),
            "@js": path.resolve(__dirname, "./src/js")
        }
    },

代码实战改写 

// commonjs的导入
// const { getPrice } = require('./js/t1');
// 配置resolve后的写法
const { getPrice } = require('@js/t1');

// ES6的导入
// import { sum } from './js/t2.js';
// 配置resolve后的写法
import { sum } from '@js/t2';

// 导入创建html的js
// import './js/createHtml.js';
// 配置resolve后的写法
import '@js/createHtml';

// 导入需要babel转换的js文件
// import './js/ypf1.js';
// 配置resolve后的写法
import '@js/ypf1';// 调用vue相关
import {createApp} from 'vue';
// import App from './vue/App.vue';
// 配置resolve后的写法
import App from '@/vue/App';

五. 区分开发/生产环境实战

1. 实现思路

 编写多个的配置文件,开发和生成时,分别加载不同的配置文件即可。

2. 实现步骤

(1). 通过指令安装下面程序,用于合并js文件

 【npm install webpack-merge -D

(2). 在config目录下新建3个js文件:

webpack.common.conf.js (公共的)

第四节:Webpack本地服务器搭建、剖析devServer的HRM热替换和其它配置、resolve模块解析、区分开发/生产环境方案实战第9张第四节:Webpack本地服务器搭建、剖析devServer的HRM热替换和其它配置、resolve模块解析、区分开发/生产环境方案实战第10张
// 这里必须通过 commonjs的写法配置,不能写 ES6的写法
const path = require('path');
// 导入插件
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { DefinePlugin } = require("webpack");
const { VueLoaderPlugin } = require('vue-loader/dist/index');

module.exports = {
    target: "web",
    entry: "./src/main.js", //入口文件
    output: {
        path: path.resolve(__dirname, "../build"), //打包后存放路径, 必须写绝对路径
        filename: "bundle.js" //打包后的文件名称
    },
    resolve: {
        extensions: [".js", ".json", ".mjs", ".vue", ".ts", ".jsx", ".tsx"], //vue ts jsx tsx 是自己添加的后缀
        alias: {
            "@": path.resolve(__dirname, "../src"),
            "@js": path.resolve(__dirname, "../src/js")
        }
    },
    module: {
        rules: [{
                test: /.css$/, //(表示所有的css结尾的文件都进行匹配)
                use: ["style-loader", "css-loader"]
            },
            {
                test: /.less$/, //(表示所有的less结尾的文件都进行匹配)
                use: ["style-loader", "css-loader", "less-loader"]
            },
            // 文件解析功能,"asset/resource"(等价于file-loader )
            {
                test: /.(jpe?g|png|gif|svg)$/,
                type: "asset/resource",
                generator: {
                    filename: "img/[name]_[hash:6][ext]"
                }
            },
            // 解析字体(也可以用file-loader处理)
            {
                test: /.(eot|ttf|woff2?)$/,
                type: "asset/resource",
                generator: {
                    filename: "font/[name]_[hash:6][ext]"
                }
            },
            // Vue解析打包
            {
                test: /.vue$/,
                loader: "vue-loader"
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./public/index.html",
            title: "hello webpack"
        }),
        new DefinePlugin({
            BASE_URL: "'./'",
            __VUE_OPTIONS_API__: true,
            __VUE_PROD_DEVTOOLS__: false
        }),
        new VueLoaderPlugin()
    ]
}
View Code

注意:

  (1). entry: "./src/main.js", 入口文件的位置,不需要改成 ../src/main.js,因为入口文件其实是和另一个属性时有关的 context,默认应该是webpack的启动目录(当前路径)

  (2). 其它的地方需要相应的改变路径,比如:path: path.resolve(__dirname, "../build"),

webpack.dev.conf.js(开发时用)

第四节:Webpack本地服务器搭建、剖析devServer的HRM热替换和其它配置、resolve模块解析、区分开发/生产环境方案实战第11张第四节:Webpack本地服务器搭建、剖析devServer的HRM热替换和其它配置、resolve模块解析、区分开发/生产环境方案实战第12张
const path = require('path');
const { merge } = require('webpack-merge');
const commonConfig = require('./webpack.common.conf');

module.exports =merge(commonConfig, {
    mode: "development", // 设置模式, development 开发阶段, 会设置development, production 准备打包上线的时候, 设置production(默认)
    devtool: "source-map", // 设置source-map, 建立js映射文件, 方便调试代码和错误(配合上面的development)
    devServer: {
        static: {
            directory: path.join(__dirname, 'public'), //表示从这个文件夹里找打包后没有找到的文件(打包是打src文件夹)
        },
        hot: true,
        host: "localhost",
        port: 9999,
        open: true,
        compress: true,
        // 下面是代理相关的配置
        // proxy: {
        //     "/api": {
        //         target: "http://localhost:8888",
        //         pathRewrite: {
        //             "^/api": ""
        //         },
        //         secure: false,
        //         changeOrigin: true
        //     }
        // }
    },
})
View Code

注意:

  需要合并webpack.common.conf.js  

webpack.pro.conf.js(生产时用)。

第四节:Webpack本地服务器搭建、剖析devServer的HRM热替换和其它配置、resolve模块解析、区分开发/生产环境方案实战第13张第四节:Webpack本地服务器搭建、剖析devServer的HRM热替换和其它配置、resolve模块解析、区分开发/生产环境方案实战第14张
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const CopyWebpackPlugin = require('copy-webpack-plugin');
const { merge } = require('webpack-merge');
const commonConfig = require('./webpack.common.conf');

module.exports =merge(commonConfig, {
    mode: "production", // 设置模式, development 开发阶段, 会设置development, production 准备打包上线的时候, 设置production(默认)
    plugins: [
        new CleanWebpackPlugin(),
        new CopyWebpackPlugin({
            patterns: [{
                from: "public", //设置从哪一个源中开始复制;
                // to: "./",    //复制到的位置,可以省略,会默认复制到打包的目录下;
                globOptions: { //下面配置忽略清单
                    ignore: [
                        "**/index.html"
                    ]
                }
            }]
        }),
    ]
})
View Code

注意:

  需要合并webpack.common.conf.js  

(3). 在package.json中修改相关指令的调用文件

  "scripts": {
    "build": "webpack --config ./config/webpack.pro.conf.js",
    "serve": "webpack serve --config ./config/webpack.dev.conf.js"
  },

(4). 测试 

  【npm run build】打包

 【npm run serve】开发运行

 

 

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 

免责声明:文章转载自《第四节:Webpack本地服务器搭建、剖析devServer的HRM热替换和其它配置、resolve模块解析、区分开发/生产环境方案实战》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇使用 AFNetworking 进行 XML 和 JSON 数据请求七天开发进度(六)(微信小程序版(一))下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

点击li获取下标的几种方式(原生JS实现)

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta...

webpack -- element-ui 的按需引入

简单说明原理: 使用babel-plugin-component实现按需引入、打包。将webpack配置成多入口,保证最终打包的目录结构符合babel-plugin-component插件的要求,实现按需加载 element源码关于按需引入的研究: 1、build目录中是cooking配置文件,cooking是饿了么前端研发的基于webpack的前端构建...

windows下安装Sonar

1、sonar安装:   sonar有三部分组成:   1、服务端:显示分析结果和sonar相关配置   2、客户端:对项目运行源代码进行运算和分析   3、数据库:存储sonar配置和代码分析结果的数据库 2、sonar下载:   官网地址:https://www.sonarqube.org/   下载你中意版本的zip包,放在想要安装的目录,linux...

C++(四十八) — string容器的基本操作

参考博客:https://blog.csdn.net/qq_37941471/article/details/82107077 https://www.cnblogs.com/danielStudy/p/7127564.html#top 1、声明一个字符串 标准库类型string表示可变长的字符序列,为了在程序中使用string类型,我们必须包含头文件:#...

NDK+MSYS2+Android sdk编译opencv源码

由于今天太晚了,详细笔记有空再记。     要添加的有ANDROID_ABI,这个根据需求添加自己需要的ABI          然后是ANDROID_STL,因为gunstl已经不被支持,这里使用c++_shared或c++_static都可以。    然后是ANDROID_STL,因为gunstl已经不被支持,这里使用c++_shared或c++_st...

js-实现鼠标滑轮滚动实现换页

html页面: 1 <!--首页一--> 2 <div id="nav_div1"><div class="nav_size"></div></div> 3 4 <!--首页二--> 5 <div id="nav_div2"></div> 6 7 <!...