学习webpack系列之四 ---- (学习开发环境)

学习webpack系列之四 ---- (学习开发环境)

本章所用的代码继续沿用上一章(输出管理)的代码。
在开始之前我们要想想,为什么要了解webpack的开发环境?
其实很简单,自动化打包工具就是为我们的开发提供便利的。之前的几个章节讲的都是比较基础的一些功能以及用法,我们的目的就是要在开发的过程中尽可能的提高工作效率,所以我们有必要来学习他的一个开发环境的配置。
OK准备好了我们就开始!

摸鱼到国庆

一、开发环境MODE

mode有三个参数:none,development,production。如果没有设置,webpack 会给 mode 的默认值设置为 production。

选项描述
none不使用任何默认优化选项
development会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 development. 为模块和 chunk 启用有效的名
production会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 production。为模块和 chunk 启用确定性的混淆名称,FlagDependencyUsagePlugin,FlagIncludedChunksPlugin,ModuleConcatenationPlugin,NoEmitOnErrorsPlugin 和 TerserPlugin

实际上,三种模式下是分别需要三个配置文件的,文章之前用的webpack.config.js是基础文件。也就是说如果选择none模式的时候,如果项目目录下有webpack.custom.config.js该文件的话,webpack就会优先加载该文件,而不是加载webpack.config.js文件。各模式对应的文件名称如下:

选项文件
none优先加载webpack.custom.config.js
development优先加载webpack.development.config.js
production优先加载webpack.production.config.js

但是如果不想配置那么多文件,只想用webpack.config.js一个文件来更改打包行为,则必须将配置导出为函数,而不是导出对象:

var config = {
  entry: './app.js',
  //...
};

module.exports = (env, argv) => {
  if (argv.mode === 'development') {
    config.devtool = 'source-map';
  }

  if (argv.mode === 'production') {
    //...
  }

  return config;
};

二、使用sourcemap

说到sourcemap,可以看看我以前写的一篇文章:sourcemap传送地址

当 webpack 打包源代码时,可能会很难追踪到 error(错误) 和 warning(警告) 在源代码中的原始位置。例如,如果将三个源文件(a.js, b.js 和 c.js)打包到一个 bundle(bundle.js)中,而其中一个源文件包含一个错误,那么堆栈跟踪就会直接指向到 bundle.js。你可能需要准确地知道错误来自于哪个源文件,所以这种提示这通常不会提供太多帮助。

为了更容易地追踪 error 和 warning,JavaScript 提供了 source maps 功能,可以将编译后的代码映射回原始源代码。如果一个错误来自于 b.js,source map 就会明确的告诉你。

sourcemap的作用就是用来溯源代码。

sourcemap 有许多 可用选项,请务必仔细阅读它们,以便可以根据需要进行配置。

 const path = require('path');
 const HtmlWebpackPlugin = require('html-webpack-plugin');

 module.exports = {
   mode: 'development',
   entry: {
     index: './src/index.js',
     printer: './src/print.js',
   },
   devtool: 'inline-source-map', // 添加这里
   plugins: [
     new HtmlWebpackPlugin({
       title: 'Development',
     }),
   ],
   output: {
     filename: '[name].bundle.js',
     path: path.resolve(__dirname, 'dist'),
     clean: true,
   },
 };

然后我们把print.js修改一下,写一个错误:

export default function printMe() {
  conle.log('I get called from print.js!');
}

接着观察效果:
sourcemap效果
注意,他直接指出了,在文件当中的第2行出现了错误,如果没有配置,他只会单独报错,而不会帮你具体指出错误在哪里,这就是sourcemap的好处。

三、了解观察模式

在学习配置热加载之前,我们先来了解一下webpack的观察模式。

我们添加一个用于启动 webpack watch mode 的 npm scripts:

 {
   "name": "webpack-simple-project",
   "version": "1.0.0",
   "description": "",
   "private": true,
   "scripts": {
     "test": "echo \"Error: no test specified\" && exit 1",
     "watch": "webpack --watch", // 添加这里
     "build": "webpack"
   },
   "keywords": [],
   "author": "",
   "license": "ISC",
   "devDependencies": {
     "html-webpack-plugin": "^4.5.0",
     "webpack": "^5.4.0",
     "webpack-cli": "^4.2.0"
   },
   "dependencies": {
     "lodash": "^4.17.20"
   }
 }

现在,你可以在命令行中运行 npm run watch,然后就会看到 webpack 是如何编译代码。 然而,你会发现并没有退出命令行。这是因为此 script 当前还在 watch 你的文件。

npm run watch

然后我们把原来的print.js的文件修改回来:

export default function printMe() {
  console.log('I get called from print.js!');
}

现在,保存文件并检查 terminal(终端) 窗口。应该可以看到 webpack 自动地重新编译修改后的模块!

唯一的缺点是,为了看到修改后的实际效果,你需要刷新浏览器。如果能够自动刷新浏览器就更好了,因此接下来我们会尝试通过 webpack-dev-server 实现此功能,接着看。

四、配置项目热加载

使用 webpack-dev-server:webpack-dev-server 为你提供了一个基本的 web server,并且具有 live reloading(实时重新加载) 功能。

首先下载安装包:

npm install --save-dev webpack-dev-server

接着修改配置文件,告知 dev server,从什么位置查找文件:

const path = require('path');
 const HtmlWebpackPlugin = require('html-webpack-plugin');

 module.exports = {
   mode: 'development',
   entry: {
     index: './src/index.js',
     print: './src/print.js',
   },
   devtool: 'inline-source-map',
   // 这里添加devServer
   devServer: {
     static: './dist',
     hot: true
   },
   plugins: [
     new HtmlWebpackPlugin({
       title: 'Development',
     }),
   ],
   output: {
     filename: '[name].bundle.js',
     path: path.resolve(__dirname, 'dist'),
     clean: true,
   },
 };

以上配置告知 webpack-dev-server,将 dist 目录下的文件 serve 到 localhost:8080 下。

webpack-dev-server 会从 output.path 中定义的目录为服务提供 bundle 文件,即,文件将可以通过 http://[devServer.host]:[devServer.port]/[output.publicPath]/[output.filename] 进行访问。

最后我们添加一个可以直接运行 dev server 的 script,并将其运行起来:

 {
   "name": "webpack-simple-project",
   "version": "1.0.0",
   "description": "",
   "private": true,
   "scripts": {
     "test": "echo \"Error: no test specified\" && exit 1",
     "watch": "webpack --watch",
     "start": "webpack serve --open", // 添加这里
     "build": "webpack"
   },
   "keywords": [],
   "author": "",
   "license": "ISC",
   "devDependencies": {
     "html-webpack-plugin": "^4.5.0",
     "webpack": "^5.4.0",
     "webpack-cli": "^4.2.0",
     "webpack-dev-server": "^3.11.0"
   },
   "dependencies": {
     "lodash": "^4.17.20"
   }
 }

现在,在命令行中运行 npm start,我们会看到浏览器自动加载页面。如果你更改任何源文件并保存它们,web server 将在编译代码后自动重新加载。试试看!

自动刷新

这里提示一下,关于hot的配置,如果我们运用webpack-dev-server的话呢,只需要关注这一个配置项就足够了。但如果我们在开发的过程中,有其他需求,需要配置自己的server的话,那就需要深入了解。这点我后续会继续更新文章,毕竟比较复杂。

而关于自己配置的server,我们可以接着看。因为随着项目的增量和需求的增加,我们是很有可能需要自己配置符合项目调试的server的。虽然这点可能平时不太会用得上,但是个人认为还是有必要了解一下的。各位看官自行取舍~

五、配置项目热加载server

使用 webpack-dev-middleware:webpack-dev-middleware 是一个封装器(wrapper),它可以把 webpack 处理过的文件–compiler发送到一个 server。webpack-dev-server 在内部使用了这个插件,然而它也可以作为一个单独的 package 来供我们配置使用,以便根据需求进行更多自定义设置。下面是一个 webpack-dev-middleware 配合 express server 的示例。

首先,安装 express 和 webpack-dev-middleware:

npm install --save-dev express webpack-dev-middleware

现在,我们需要调整 webpack 配置文件,以确保 middleware(中间件) 功能能够正确启用:

const path = require('path');
 const HtmlWebpackPlugin = require('html-webpack-plugin');

 module.exports = {
   mode: 'development',
   entry: {
     index: './src/index.js',
     print: './src/print.js',
   },
   devtool: 'inline-source-map',
   // 将devServer去掉,用我们自己配置的服务,不需要 webpack-dev-server
   // devServer: {
   //   static: './dist',
   // },
   plugins: [
     new HtmlWebpackPlugin({
       title: 'Development',
     }),
   ],
   output: {
     filename: '[name].bundle.js',
     path: path.resolve(__dirname, 'dist'),
     clean: true,
     publicPath: '/', // 注意这个
   },
 };

我们将会在 server 脚本使用 publicPath,前面也提及到了,webpack-dev-server是通过http://[devServer.host]:[devServer.port]/[output.publicPath]/[output.filename] 进行访问的。所以我们这里必须要设置这个参数,以确保文件资源能够正确地 serve 在 http://localhost:3000 下,稍后我们会指定 port number(端口号)。

重新整理一下项目目录,增加server.js,配置属于我们自己的服务:

 webpack-simple-project
  |- package.json
  |- webpack.config.js
  |- server.js
  |- /dist
  |- /src
    |- index.js
    |- print.js
  |- /node_modules

server.js文件当中键入以下代码:

const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');

// 实例化 express
// 引入 webpack 配置文件
// 将 config 打包成 compiler package
const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);

// 告知 express 使用 webpack-dev-middleware
// 以及将 compiler package 作为基础配置
app.use(
  webpackDevMiddleware(compiler, {
    publicPath: config.output.publicPath,
  })
);

// 将文件 serve 到 port 3000。
app.listen(3000, function () {
  console.log('Example app listening on port 3000!\n');
});

现在,添加一个 npm script,然后运行 server:

 {
   "name": "webpack-simple-project",
   "version": "1.0.0",
   "description": "",
   "private": true,
   "scripts": {
     "test": "echo \"Error: no test specified\" && exit 1",
     "watch": "webpack --watch",
     "start": "webpack serve --open",
     "server": "node server.js", // 添加这个
     "build": "webpack"
   },
   "keywords": [],
   "author": "",
   "license": "ISC",
   "devDependencies": {
     "express": "^4.17.1",
     "html-webpack-plugin": "^4.5.0",
     "webpack": "^5.4.0",
     "webpack-cli": "^4.2.0",
     "webpack-dev-middleware": "^4.0.2",
     "webpack-dev-server": "^3.11.0"
   },
   "dependencies": {
     "lodash": "^4.17.20"
   }
 }

自行配置服务效果
可以看见listening on port 3000! 就是成功了,页面也成功的运行起来了:

自行配置服务效果

以上就是我们自行配置webpack服务的效果,如果你已经跟着写一遍并且理解了,我相信你会明白其中的一些妙不可言的地方,因为这确实是特别的人性化,自己想配置什么配置什么,不受约束,nice~

下一篇我们趁热打铁,继续学习webpack的模块热替换章节,就是所谓的热更新功能!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值