webpack打包与webpack-dev-server热替换

说在前面:本文主要是提供webpack4.5版本的热替换无效的一种解决方案,借助webpack-dev-server-output插件,感兴趣的小伙伴可以交流讨论哦.大致效果如下:

HMR.gif


背景

搞前端开发的同学肯定都知道webpack吧?连我这菜鸟都知道点呢,你们肯定知道的!大家都知道,webpack使用起来很是愉快,几条命令就完成了我们对静态资源的打包(图片/样式/脚本等),但是其配置文件却着实令人头痛!而想要在开发中愉快高效地使用webpack,就需要对配置文件webpack.config.js下些功夫!学习资料包括webapck官方文档和众多的配置和优化相关的博客,这里就不赘述了!

webpack

而随着webpack4.x的发布,配置文件做了优化,变得稍稍简单了一些,这不手贱没忍住,升级了webpack4.5版本,于是按照之前的配置有些东西不好使了!
我能怎么办我也很无奈


webpack 4.x

webpack4.xCLI抽离出为单独的包webpack-cli,需要npm install webpack-cli -D单独全局安装不然无法进行编译.此外,对配置文件做了一些变动,像是新增的mode项(可以配置执行developmentproduction两种打包模式)等细节不赘述(主要是我也没掌握/捂脸).而我要讲的是我按照官网和众多博客配置的HMR(Hot Module Replacement)不起作用,及最后寻得的解决方案!


热替换(Hot Module Replacement)

所谓热替换,就是在不刷新网页的情况下,改变代码后,会自动编译并更新页面内容,是不是很神奇?相比传统的,变更代码后运行webpack重新打包,然后F5刷新页面,是不是简单了好多?想要了解其原理的同学可以看这里.而像我这种'懒癌+强迫症'患者,得知有这么个'偷懒的'机会,是一定不会放过的,所以就陷入了不断的挖坑填坑中...无法自拔啊!

1. 准备项目

  • 项目目录
- project 
  - dist
    main-build.js
    main-build.js.map
    index.html
  - src
    - views
      Home.vue
      About.vue
      index.js
    main.js
    route.config.js
  - test
  package.json
  webpack.base.config.js
  webpack.dev.config.js
  webpack.config.js  

项目源码在这里

2. 如何实现?

在开始之前,哪啊不能从源码上理解其运行机制,但是也要对大致的配置及作用有所了解,可以看下这里webpack develement.可以了解到实现HMR有几种方式,webpack's Watch Mode/webpack-hot-middleware+express/webpack-dev-derver,后两者都需要在配置里面加入devServer配置项.下面就是具体试下那步骤进行介绍.

步骤1 安装依赖包

  • 假设你已经安装了node.js较新的版本(以为webpack 4.xnode版本进行了限制,保证最新就好了),这样便有了npm包管理器
  • 全局安装webpack最新版本的包和cli:npm install webpack webpack-cli -g
  • 之后本地开发安:npm install webpack webpack-cli webpack-dev-server --save-dev

步骤2 配置webpack.config.js文件

考虑到不同打包需求,往往会又多份配置文件,我们暂时配置三个:base/dev/build

  • 不同打包模式配置文件的公用部分,webpack.base.config.js
// 引入node相关模块
const fs = require("fs");
const path = require("path");
const webpack = require("webpack");
const CleanWebpackPligin = require("clean-webpack-plugin");

// 设置路径
module.exports = {
  // 打包开始的地方,即从这里开始分析模块和资源依赖
  entry: "./src/route.js",
  // 输出
  output: {
    // 输出路径
    path: path.resolve(__dirname, "./dist"),
    // 输出文件名
    filename: "[name]-build.js"
  },
  module: {
    rules: [
      {
        // 解析.vue文件
        test: /\.vue$/,
        loader: "vue-loader"
      }
    ]
  },
  plugins: [
    // 每次重新打包时清楚原本的内容
    new CleanWebpackPligin("./dist", {
      exclude: ["index.html"]
    })
  ],
  resolve: {
    // 通过.vue文件进行模板编译时,需要添加此配置
    alias: {
      vue$: "vue/dist/vue.common.js"
    }
  }
};
  • 开发模式下的配置文件:webpack.dev.config.js
const webpack = require("webpack");
const WebpackDevServerOutput = require("webpack-dev-server-output");
const baseConfig = require("./webpack.base.config");

// 开发模式
baseConfig.mode = "development";
// 打包文件在内存中的输出路径,可以通过http://localhost:8066/assets/访问
baseConfig.output.publicPath = "/assets/";
// 方便追踪源代码中的错误
baseConfig.devtool = "source-map";
// 服务配置
baseConfig.devServer = {
  // 发布服务的文件夹
  contentBase: "./dist",
  host: "127.0.0.1",
  port: 8066,
  // 声明为热替换
  hot: true,
  // 第一次打包时打开浏览器
  open: true,
  // 与output中的内容保持一致
  publicPath: "/assets/"
};
baseConfig.plugins.push(
  ...[
    new webpack.NamedModulesPlugin(),
    // 热替换插件
    new webpack.HotModuleReplacementPlugin(),
    // 将webpack-dev-server在内存中打包的文件输出为本地文件
    new WebpackDevServerOutput({
      path: "./dist/assets",
      isDel: true
    })
    // ...
  ]
);
module.exports = baseConfig;
  • 生产模式下的配置文件:`webpack.config.js'
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");

const baseConfig = require("./webpack.base.config");

baseConfig.mode = "production";
baseConfig.plugins.push(
  ...[
    // 压缩代码 生产模式会默认调用改插件
    new UglifyJsPlugin()
    // ...
  ]
);

步骤3 添加scripts

打开项目的package.json文件,找到scripts,然后添加如下内容:

 "scripts": {
    // 生产模式 默认调用webpack.config.js
    "build": "webpack",
    // 开发模式 指定调用webpack.dev.config.js
    "dev": "webpack-dev-server --config webpack.dev.config.js"
  }

这样在命令行输入npm run dev便会编译本地文件,并打开浏览器显示出devServer中配置的contentBase中的内容,默认是其中的idnex.html.

结果并不如愿

image.png

Waht?我明明是按照官方 文档配置的啊?


image.png

问题是通过devServer.publicPath无法访问到内存中创建的打包文件main-build.js!!!
查看了N多博客之后,还是一头雾水,问题没能解决.但是想着,如果把内存中的文件输出到本地,然后发布出来,是不是就可以访问了?

解决方案

于是在npm上搜索到了webpack-dev-server-output插件,正是我想要的,而且配置也很简单.

  • 对配置文件做如下更改:在webpack.dev.config.jsplugins数组中如下添加插件配置:
new WebpackDevServerOutput({
    // 文件输出路径,这里设置为devServer服务路径的子路径
    // 这样就可以通过URL访问到了
    path: "./dist/assets",
    // 重新编译时删除之前你的文件
    // 这里可能会有效率问题
    isDel: true
})
  • 问题:每次重新更改触发重新编译后,都会将./assets下原始的文件删除掉,重新写入,会带来性能的问题

写在最后:热替换最初的目的就是为了减去重复写入文件的麻烦,所以把重新编译的文件放在内存中,通过URL访问,但是无奈404,只能暂且使用该方法解决,至少现在不用每次更新都输入密令然后F5刷新了.

如果哪位大神有更好的解决办法,还请指点迷津啊!拜托拜托!


参考


如果您感觉有所帮助,或者有问题需要交流,欢迎留言评论,非常感谢!
前端菜鸟,还请多多关照!


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容