Webpack教程二

1. watch观察模式

在每一次修改代码后,我们都要执行npm run build 进行打包,这样不是很方便。为了简化流程,我们有两种方式。

第一,可以在package.json中添加watch,之后每一次修改代码保存后都会自动打包一次。

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --watch"
  },

用VScode的Live Server打开的页面也会自动更新

第二,在webpack.config.js中配置watch

module.exports={
    watch:true,
    ...
}

2. webpack-dev-server

使用watchlive server可以实现自动更新,但是其存在问题为:

  • 修改时,所有源代码都会重新编译
  • 每次编译成功后都要进行文件读写(dist文件生成)
  • 不能实现局部更新

这时我们需要webpack-dev-serverwebpack-dev-server为你提供了一个简单的 web 服务器,并且能够实时重新加载

1、下载

npm i webpack-dev-server -D

2、在package.json中配置serve如下

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "serve": "webpack serve"
},

3、在终端执行npm run serve,这时并不会生成dist文件,而是将资源保存在内存中。我们可以使用http://localhost:8080/打开页面,从而使我们的资源运行在一个本地服务器上。

除此之外,我们还可以在webpack.config.js中配置devServer。

devServer:{
    static:{
    	// 此路径下的打包文件可在浏览器中访问。
    	//默认 publicPath 是 "/",所以你的包index.js可以通过 http://localhost:8080/index.js 访问。
        publicPath:'/lg/',
    }
},

这时如果把output.publicPath也设置为'/lg'则可以在该目录下正确访问页面
在这里插入图片描述
其他配置:

devServer:{
	// 在构建失败时不刷新页面作为回退 ,也就是说当页面更新有语法错误时,不会刷新页面
    hot:'only',
    // 指定服务开启的端口号
    port:7788,
    // 在服务器已经启动后自动打开浏览器
    open:true
    // 对文件进行压缩处理后再返回给客户端进行展示,有性能提升
    compress: true,
    // 刷新页面后如果没有找到对应的资源,就会显示index.html
    historyApiFallback: true,
    // 配置代理服务器,解决跨域资源请求问题
    proxy: { 
      '/api': {
       // 对 /api/users 的请求会将请求代理到 http://localhost:3000/api/users。
        target: 'http://localhost:3000',
        // 如果不希望传递/api,则需要重写路径
        pathRewrite: { '^/api': '' },
        // ture表示不接受在 HTTPS 上运行且证书无效的后端服务器
        secure: false,
        // 默认情况下,代理时会保留主机头的来源,可以将 changeOrigin 设置为 true 以覆盖此行为。
        changeOrigin: true,
      },
    },
},

3. webpack-dev-middleware

webpack-dev-middleware 是一个容器,它可以把 webpack 处理后的文件传递给一个服务器。

// express框架用于搭建web服务器
npm i express
npm i webpack-dev-middleware

express框架的基本使用可以看这一篇文章

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

const express = require('express')
const app = express()

// 获取配置文件
const config = require('./webpack.config.js')
const compiler = webpack(config)

app.use(webpackDevMiddleware(compiler))

//开启端口上的服务
app.listen(3000,()=>{
    console.log('服务器运行在3000端口');
})

这样我们就可以访问express所搭建的服务器资源了
在这里插入图片描述

4. HMR

模块热替换(Hot Module Replacement 或 HMR)是 webpack 提供的最有用的功能之一。它允许在运行时更新各种模块,而无需进行完全刷新。

也就是说如果当你更新一个模块的代码时,其他未修改的代码不会受影响,重新更新。

1、webpack.config.js中的配置如下

module.exports={
	...
	devServer:{
        hot:true
    }
}

2、在入口文件index.js中指定要热替换的模块

if(module.hot){
    module.hot.accept(['./title.js'],()=>{
        console.log('title模块更新啦~');
    })
}

3、局部更新
在这里插入图片描述

5. Vue组件支持热更新

Vue Loader支持用于 vue 组件的 HMR,提供开箱即用体验。

1、下载

npm i vue@2 -D
npm i vue-loader@14 -D

2、webpack.config.js中进行配置

 {
      test:/\.vue$/,
      use:['vue-loader']
  }

3、示例

index.js

import './title'
import Vue from 'vue'
import App from './App.vue'

new Vue({
    render:h=>h(App)
}).$mount('#root')

app.vue

<template>
  <div class='one'>{{msg}}</div>
</template>

<script>
export default{
    data(){
        return{
            msg:'hello!'
        }
    }
}
</script>

<style>
    .one{
        color:red;
    }
</style>

如下:
在这里插入图片描述

6. 解析Resolve

Resolve配置可以设置模块如何被解析

绝对路径:不需要进行解析
相对路径:在 import/require 中给定的相对路径,会拼接此上下文路径,来生成模块的绝对路径。
模块路径:在 resolve.modules 中指定的所有目录中检索模块。
modules: ['node_modules']

一旦根据上述规则解析路径后,resolver 将会检查路径是指向文件还是文件夹

如果路径指向文件:

  • 如果文件具有扩展名,则直接将文件打包。
  • 否则,将使用 resolve.extensions 选项作为文件扩展名来解析,此选项会告诉解析器在解析中能够接受那些扩展名(例如 .js,.jsx)。
extensions: ['.js', '.json', '.wasm'],

如果路径指向一个文件夹,则进行如下步骤寻找具有正确扩展名的文件:

  • 如果文件夹中包含 package.json 文件,则会根据 resolve.mainFields 配置中的字段顺序查找,并根据 package.json 中的符合配置要求的第一个字段来确定文件路径。
mainFields: ['browser', 'module', 'main'],
  • 如果不存在 package.json 文件或 resolve.mainFields 没有返回有效路径,则会根据 resolve.mainFiles 配置选项中指定的文件名顺序查找,看是否能在 import/require 的目录下匹配到一个存在的文件名。
 mainFiles: ['index'],
  • 然后使用 resolve.extensions 选项,以类似的方式解析文件扩展名。

resolve.alias用于创建 import 或 require 的别名,来确保模块引入变得更简单。例如,一些位于 src/ 文件夹下的常用模块:

resolve: {
    alias: {
      @: path.resolve(__dirname, 'src')
    },
  },

原本导入如下

import './title'

现在导入

import '@/title'

7. source-map

当 webpack 打包源代码时,可能会很难追踪到 error(错误) 和 warning(警告) 在源代码中的原始位置。例如,如果将三个源文件(a.js, b.js 和 c.js)打包到一个 bundle(bundle.js)中,而其中一个源文件包含一个错误,那么堆栈跟踪就会直接指向到 bundle.js。
为了更容易地追踪 error 和 warning,JavaScript 提供了 source maps 功能,可以将编译后的代码映射回原始源代码。如果一个错误来自于 b.js,source map 就会明确的告诉你。

devtool:'source-map'

浏览器中要sour允许使用source-map
在这里插入图片描述

8. devtool

devtool用于选择一种 source map 风格来增强调试过程。不同的值会明显影响到构建(build)和重新构建(rebuild)的速度。

  • 对于开发环境,通常希望更快速的 source map,需要添加到 bundle 中以增加体积为代价
  • 对于生产环境,则希望更精准的 source map,需要从 bundle 中分离并独立存在。

以下选项非常适合开发环境

  • eval - 每个模块都使用 eval() 执行,并且都有 //@ sourceURL。此选项会非常快地构建。主要缺点是,由于会映射到转换后的代码,而不是映射到原始代码(没有从 loader 中获取 source map),所以不能正确的显示行数。
  • eval-source-map - 每个模块使用 eval() 执行,并且 source map 转换为 DataUrl 后添加到 eval() 中。初始化 source map 时比较慢,但是会在重新构建时提供比较快的速度,并且生成实际的文件。行数能够正确映射,因为会映射到原始代码中。它会生成用于开发环境的最佳品质的 source map。
  • eval-cheap-source-map - 类似 eval-source-map,每个模块使用 eval() 执行。这是 “cheap(低开销)” 的 source map,因为它没有生成列映射(column mapping),只是映射行数。它会忽略源自 loader 的 source map,并且仅显示转译后的代码,就像 eval devtool。
  • eval-cheap-module-source-map - 类似 eval-cheap-source-map,并且,在这种情况下,源自 loader 的 source map 会得到更好的处理结果。然而,loader source map 会被简化为每行一个映射(mapping)。

这些选项通常用于生产环境中

  • (none)(省略 devtool 选项) - 不生成 source map。这是一个不错的选择。
  • source-map - 整个 source map 作为一个单独的文件生成。它为 bundle 添加了一个引用注释,以便开发工具知道在哪里可以找到它。

以下选项对于开发环境和生产环境并不理想。他们是一些特定场景下需要的,例如,针对一些第三方工具。

  • inline-source-map - source map 转换为 DataUrl 后添加到 bundle 中。
  • cheap-source-map - 没有列映射(column mapping)的 source map,忽略 loader source map。
  • inline-cheap-source-map - 类似 cheap-source-map,但是 source map 转换为 DataUrl 后添加到 bundle 中。
  • cheap-module-source-map - 没有列映射(column mapping)的 source map,将 loader source map 简化为每行一个映射(mapping)。
  • inline-cheap-module-source-map - 类似 cheap-module-source-map,但是 source mapp 转换为 DataUrl 添加到 bundle 中。

9. 区分环境配置

在开发环境中,我们需要强大的 source map 和一个有着 live reloading(实时重新加载) 或 hot module replacement(热模块替换) 能力的 localhost server。

而生产环境目标则转移至其他方面,关注点在于压缩 bundle、更轻量的 source map、资源优化等,通过这些优化方式改善加载时间。

由于要遵循逻辑分离,建议为每个环境编写彼此独立的 webpack 配置

当 webpack 配置对象导出为一个函数时,可以向起传入一个"环境对象(environment)"。

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "serve": "webpack serve",
    "build2": "webpack --config ./config/webpack.common.js --env production",
    "serve2": "webpack serve --config ./config/webpack.common.js --env development"
  },

根据CLI命令绝对配置文件

// webpack-merge 提供一个merge函数用于合并数组,或者对象
const {merge} = require('webpack-merge')

const prodConfig = require('./webpack.prod')
const devConfig = require('./webpack.dev')
const commonConfig={
    //基本配置
}
module.exports=(env)=>{
    const isProduction = env.Production;
    const config = isProduction?prodConfig:devConfig;
    const mergeConfig=merge(commonConfig,config)
    return mergeConfig
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

焦妮敲代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值