webpack5基础应用(3)

2023-11-07 295 0

一. 搭建开发环境

在此之前我们很多工作都是手工的,比如每次打开html文件都需要右键在浏览器打开,还有每次更新代码都需要重新编译,而且只能手动的去刷新浏览器才能看到新效果等等。下面我们通过搭建开发环境去解决这个问题。

1. mode选项

修改mode配置:

module.exports = {
    ... ...
    mode: "development", //开发模式

    ... ...
};

2. 使用source map

使用source map进行代码调试,比如不小心将helloworld.js文件中的console写成了cnosole,执行打包命令之后,在代码里面不能直观的看出发生错误的位置:

那我们通过浏览器帮助我们检查,浏览器打开html之后发现错误是在hello-world.js的第六行:

点击之后发现,这个代码并不是我们源文件中的:

这时我们可以通过一种方式精准的锁定代码出错的位置。

修改webpack配置:

module.exports = {
    ... ...
    //在浏览器运行编译后的代码时,可以对应到编译前也就是开发编写的代码。对调试非常有帮助。

    devtool: "inline-source-map", 
    ... ...
};

重新编译之后,打开bundle.js,发现代码能够正常显示了:

刷新浏览器,发现错误还在,但是hello-world.js的错误行数指向程序的第二行:

也就是我们真实的源代码的第二行:

3. 使用watch mode

每次编译代码时,手动运行 npx webpack 会显得很麻烦。我们可以在webpack启动时添加watch参数,如果其中一个文件被更新,代码将被重新编译,不必手动再去运行整个构建。

运行命令:

$ npx webpack --watch

这样就会实时监测我们文件的变化。修改hello-world.js,保存之后会发现程序自动执行了一次编译:

刷新浏览器,修改的地方更新过来了。

4. 使用webpack-dev-server

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

先安装:

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

配置devServer服务:

module.exports = {
    ... ...
    //本地服务配置
    devServer: {
        static: './dist', //devServer指向的物理路径 指定dist作为项目根目录
    }
};

执行命令,启动服务:

$ npx webpack-dev-server

这样我们就会启动一个http://localhost:8080/的服务。浏览器打开服务,会发现服务根目录指向了dist文件夹里:

点击app.html,打开控制台发现程序正常运行,并且热模块更新替换,实时更新也生效了。

修改代码,不手动刷新浏览器,控制台上面也实时更新了打印结果,这样webpack-dev-server就完成了自动刷新页面的功能。

其实webpack-dev-server真正的没有输出任何物理文件,它把打包输出的bundle文件放到了内存里。比如删掉dist文件夹,重新在浏览器访问,结果并没有什么问题。关闭服务,再重新启动服务,浏览器打开,结果任然能够正常运行。修改文件,在浏览器照常能够自动刷新。

二. 资源模块

到目前为止,项目只能加载js,现在我们能不能尝试混合一些其他的资源呢,比如像images。在webpack出现之前,使用类似于Grunt或者Gulp等工具来处理资源,它们奖src里面的文件移动到dist或者build中。其实webpack最出色的功能之一就是除了引入js还可以使用内置的资源模块。我们叫asset modules来引入其他任何类型的资源。asset module即资源模块,是一种模块类型,它允许我们应用webpack来打包其他的资源文件,比如像字体文件,图标文件等等。资源模块的类型称之为 asset module type ,会通过四种新的类型模块来替换所有的loader。

四种类型模块:

  • asset / resource 它会发送一个单独的文件并导出URL
  • asset / inline 它会导出一个资源的data URL
  • asset / source 会导出资源的源码
  • asset 会在导出一个Data URL 和发送一个单独文件之间自动进行选择

1. Resource资源

修改webpack.config.js文件:

module.exports = {
    ... ...
    ... ...
    //资源模块配置
    module: {
        // 规则配置,数组里面配置多个对象去加载不同类型的资源文件
        rules: [
            {
                //test+正则表达式去定义加载的文件的类型
                test: /\.png$/, // 表示以png作为扩展名的这样的类型文件
                //定义资源类型
                type: 'asset/resource',
            },
        ],
    },
};

src下新建assets文件夹,文件夹下放置.png / .svg /.jpg等不同类型文件。

在index.js里面引入文件:

import helloWorld from "./hello-world";
//资源加载进来以后,会生成一个URL,可以通过这个URL在页面上显示
import imgsrc from './assets/img01.png';
helloWorld();

const img = document.createElement('img');
img.src = imgsrc;
document.body.appendChild(img);

执行npx webpack命令,可以看到dist下面生成了一个打包的.png文件:

执行一下命令启动webpack服务,并帮我们自动打开浏览器:

$ npx webpack-dev-server --open

点击app.html,图片正常显示:

我们可以看到dist下的打包生成的图片名是webpack自动生成的,那么我们能不能自己定义图片的目录以及文件名呢?当然是可以的,有两种方法:

第一种:修改webpack.config.js文件的output,添加 assetModuleFilename 属性:

module.exports = {
    entry: "./src/index.js", //入口文件配置
    // 出口文件配置
    output: {
        filename: "bundle.js", // 指定输出文件的文件名
        // path: './dist', //报错:必须为绝对路径
        // 调用path模块的resolve方法
        path: path.resolve(__dirname, "./dist"), //指定文件输入路径
        // __dirname 表示获取到当前的webpack.config.js这个文件所在的物理路径
        // "./dist"  表示基于前面的第一个路径去找到 dist文件夹
        clean: true, //生成新文件之前,清空之前的文件
        assetModuleFilename: 'images/test.png', //资源模块的文件名,不但可以设置文件名,还可以设置路径
    }
}

执行npx webpack打包,文件生成成功:

只是,不可能我们所有的资源都叫test.png,所以我们还得去自动生成一个文件名。我们可以使用webpack自带的默认的生成文件名的方法:images/[ contenthash ][ ext ]

module.exports = {
    entry: "./src/index.js", //入口文件配置
    // 出口文件配置
    output: {
        filename: "bundle.js", // 指定输出文件的文件名
        // path: './dist', //报错:必须为绝对路径
        // 调用path模块的resolve方法
        path: path.resolve(__dirname, "./dist"), //指定文件输入路径
        // __dirname 表示获取到当前的webpack.config.js这个文件所在的物理路径
        // "./dist"  表示基于前面的第一个路径去找到 dist文件夹
        clean: true, //生成新文件之前,清空之前的文件
        //资源模块的文件名,不但可以设置文件名,还可以设置路径
        // [contenthash] 表示根据文件的内容去生成一个哈希的字符串,
        assetModuleFilename: "images/[contenthash][ext]",//扩展名可以使用原资源的扩展名 [ext]
    }
}

重新执行打包命令:

第二种:定义rules的时候添加属性 generator 。generator优先级高于output的优先级。

module.exports = {
    ... ...
    ... ...
    //资源模块配置
    module: {
        // 规则配置,数组里面配置多个对象去加载不同类型的资源文件
        rules: [
            {
                //test+正则表达式去定义加载的文件的类型
                test: /\.png$/, // 表示以png作为扩展名的这样的类型文件
                //定义资源类型
                type: 'asset/resource',
                // 定义文件的名字和路径
                generator: {
                    filename: "images/[contenthash][ext]",
                },
            },
        ],
    },
};

重新打包,资源成功被打包了。

2. inline资源

修改webpack.cong.js文件,新增rules配置:

module.exports = {
    ... ...
    ... ...
    //资源模块配置
    module: {
        // 规则配置,数组里面配置多个对象去加载不同类型的资源文件
        rules: [
            {
                //test+正则表达式去定义加载的文件的类型
                test: /\.png$/, // 表示以png作为扩展名的这样的类型文件
                //定义资源类型
                type: 'asset/resource',
                // 定义文件的名字和路径
                generator: {
                    filename: "images/[contenthash][ext]",
                },
            },
            {
                test: /\.svg$/,
                type: 'asset/inline'
            }
        ],
    },
};

引入svg资源:

import logoSvg from './assets/img02.svg';
... ...
const img2 = document.createElement("img");
img2.src = logoSvg;
document.body.appendChild(img2);

执行打包命令之后会发现,虽然我们打包成功了,但是dist下面并没有我们想要的文件:

因为我们使用的是asset inline,那么只能去浏览器去看效果了。启动服务,打开app.html:

svg图片正常加载出来了。检查第二个图片元素会发现它不是一个图片的URL,而是所谓的 Data URL base64的格式:

3. Source资源

修改webpack.config.js文件,新增rules配置:

module.exports = {
    ... ...
    ... ...
    //资源模块配置
    module: {
        // 规则配置,数组里面配置多个对象去加载不同类型的资源文件
        rules: [
            {
                //test+正则表达式去定义加载的文件的类型
                test: /\.png$/, // 表示以png作为扩展名的这样的类型文件
                //定义资源类型
                type: 'asset/resource',
                // 定义文件的名字和路径
                generator: {
                    filename: "images/[contenthash][ext]",
                },
            },
            {
                test: /\.svg$/,
                type: 'asset/inline'
            },
            {
                test: /\.txt$/,
                type: 'asset/source'
            }
        ],
    },
};

assets下新建example.txt文件。引入.txt文件。

import exampleTxt from './assets/example.txt';
... ...

const block = document.createElement("div");
block.textContent = exampleTxt;
document.body.appendChild(block);

执行打包命令之后。dist下仍旧没有生成任何文件:

启动服务在浏览器中查看,.txt文件内容显示成功:

4. 通用数据类型

修改webpack.config.js文件,新增一个资源类型:

module.exports = {
    ... ...
    ... ...
    //资源模块配置
    module: {
        // 规则配置,数组里面配置多个对象去加载不同类型的资源文件
        rules: [
            {
                //test+正则表达式去定义加载的文件的类型
                test: /\.png$/, // 表示以png作为扩展名的这样的类型文件
                //定义资源类型
                type: 'asset/resource',
                // 定义文件的名字和路径
                generator: {
                    filename: "images/[contenthash][ext]",
                },
            },
            {
                test: /\.svg$/,
                type: 'asset/inline'
            },
            {
                test: /\.txt$/,
                type: 'asset/source'
            },
            {
                test: /\.jpg$/,
                type: 'asset'
            }
        ],
    },
};

引入jpg文件。

import jpgMap from './assets/img03.jpg';
... ...
const img3 = document.createElement("img");
img3.src = jpgMap;
document.body.appendChild(img3);

执行打包命令之后发现dist下面的images下面多了一个文件:

这里有个问题,新打包生成的文件为什么在images里面,我们并没有设置generator。那他事实上是继承使用了我们在output里面指定的assetModuleFilename。

启动服务,在浏览器查看,打开app.html,图片正常显示:

检查元素,可以看到这个图片是一个实际上的本地的图片资源

我们说asset会在两种类型上做选择,很显然现在选择的是asset resource,那如何让他在asset inline上选择呢?默认情况下,webpack回去判断我们加载的资源的大小,当文件资源大于8k的时候,就会去创建一个资源了,如果小于8k,他就会作为一个inline 生成一个base64的链接。那我们能不能自己去调整一下这个临界值呢?

修改webpack.config.js 新增一个参数去调整这个临界值:

{
    test: /\.jpg$/,
    type: 'asset',
    //解析器
    parser: {
        dataUrlCondition: {
            maxSize: 4 * 1024 * 1024, //默认情况下大小为 4 * 1024
        },
    }
}

重新执行打包命令,会发现刚生成的图片文件没了:

启动服务,在浏览器打开app.html,图片正常显示,检查元素,图片为base64格式。

相关文章

webpack基础应用(6)
webpack5基础应用(5)
webpack5基础应用(4)
webpack5基础应用(2)
webpack5 基础应用(1)

发布评论