webpack学习之1.基础配置

前序

nodejs版本:10.15.1
webpack学习版本:4.43.0
在项目中初始化了package.json
学习中,依赖安装全部使用的 -D[–save-dev]

npm init -y

概念

webpack 是一个 JavaScript 应用程序的 静态模块 打包器(module bundler)。

当 webpack 处理应用程序时,它会递归地构建一个 依赖关系图 (dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块,经过预处理、编译、合并、拆分等自定义流程,打包成一个或多个 bundle。

安装

安装webpack 和 webpack-cli(webpack 4+ 需要安装 cli 以执行webpack命令)

npm install -D webpack webpack-cli

现在可以在package.json的scripts中设置脚本,执行webpack命令

// package.json
{
	"scripts": {
		"build":"webpack"
	},
	// ...
}

若想在终端(命令行工具)中直接使用webpack命令,需要使用全局安装(-g)。

执行命令

在项目根目录新建目录src并在其内部创建一个index.js文件。
执行打包命令 npm run build
执行结束,项目中新建了dist目录,webpack将src/index.js打包后的文件main.js放在了dist中。
在这里插入图片描述

关键字

entry 入口,既然要构建依赖关系,就需要知道先从哪些文件(模块)开始递归。默认为 ./src/index.js

output 出口,output配置了打包后的文件输出位置 及 如何命名。默认为 ./dist/main.js

bundles 打包的文件被输出到被称为 bundles 的文件夹。默认为 ./dist

bundle 最终打包后的文件。通常是由多个不同的模块产生,它是已经加载完毕和被编译后的源代码的最终版本。默认为 ./dist/main.js

构建依赖关系

在src目录新建文件module1.js和module2.js,并修改index.js。内容如下:

// src/module1.js
import { message } from './module2'; // js后缀可以省略
export default {
	title: 'I am module1',
	info: message
}

// src/module2.js
export var message =  'this is module2';

// src/index.js
import data from './module1';
console.log(data);

使用ES6模块语法,在module1.js中加载模块module2.js,在index.js中加载模块module1.js。模块语法参考

重新打包 npm run build
在这里插入图片描述
运行打包后的文件 ./dist/main.js 查看效果:

// 可使用node命令在终端查看:node ./dist/main.js
// 或者新建html文件引入main.js,在浏览器开发者工具console中查看。
{ title: 'I am module1', info: 'this is module2' }

这就是webpack最基础的用处,构建依赖关系图,将有依赖关系的文件打包称一个文件。

关键字

module 模块,对于webpack来说,所有的资源/文件(.js、.css、.png)都是module。如 概念 所说,webpack为这些模块,构建依赖关系图,最终打包。上面的3个js文件(index module1 module2)都是模块。

配置文件

可以在项目中创建webpack配置文件,修改webpack的默认配置。参考 配置 webpack官网
执行webpack命令时,可以指定使用的配置文件:

webpack --config xxxxxx.js

webpack默认使用当前目录下的 webpack.config.js
创建webpack.config.js并使用默认配置(下面配置并没有改变什么)

// webpack.config.js
// webpack是导出一个对象的js文件

// webpack配置是标准的 Node.js CommonJS模块
// 可以通过require(...)导入其他文件
// 可以使用常用值 __dirname 等
var path = require('path');

module.exports = {
    entry: {
        main: './src/index.js'
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].js' // name为entry定义的入口名:main
    }
}

在这里插入图片描述

Loader 预处理器

关键字

loader webpack 自身只理解 JavaScript,要处理js以外的模块(css less vue 图片等),则需要 loader 按需对文件进行预处理或“加载”。将它们转换为webpack可以处理的有效模块(js文件、Dataurl等)。

示例

比如使用css文件:
在src目录下新建 css/style.css
修改index.js中加载style.css
在dist目录下新建index.html查看效果

// src/css/style.css
h1 {
    color:blue; 
    font-size:16px;
}

// src/index.js
import './css/style.css';
import data from './module1';
// 删除 console.log(data)
var div = document.createElement('div');
div.innerHTML= `<h1>${data.title}</h1><p>${data.info}</p>`;
document.body.appendChild(div);

// dist/index.html
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <h1>I am index.html</h1>
        <script src="./main.js"></script>
    </body>
</html>

在这里插入图片描述

此时执行打包命令会报错:

You may need an appropriate loader to handle this file type, 
currently no loaders are configured to process this file.
您可能需要适当的 loader 来处理此文件类型,目前没有配置 loader 来处理此文件。

添加loader

安装 css-loader style-loader
css-loader 用于识别 模块方式 加载的css,将其转化为js代码,但并不负责应用到页面中。
style-loader 通过js创建一个<style>标签,将css插入进去。

npm install css-loader style-loader -D

在webpack.config.js 中 配置。参考 loader webpack官网

// webpack.config.js
var path = require('path');

module.exports = {
    entry: {
        main: './src/index.js'
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].js' // name为entry定义的入口名:main
    },
    module: {
        rules: [
            {
                test: /\.css$/, // 根据正则匹配.css结尾的文件
                use: [ // 配置loader,倒序使用
                    {loader: 'style-loader'},
                    {loader: 'css-loader'}
                ]
            }
        ]
    }
}

执行打包命令成功,用浏览器打开dist/index.html,样式生效,查看element
在这里插入图片描述
在这里插入图片描述

可以看到head中被创建了一个引入了css/style.css内容的<style>标签

Plugin 插件

关键字

plugin 插件,目的在于解决 loader 无法实现的其他事。

它就是一个扩展器,它丰富了wepack本身,针对是loader结束后,webpack打包的整个过程,它并不直接操作文件,而是基于事件机制工作,会监听webpack打包过程中的某些节点,执行广泛的任务。

webpack 插件是一个具有 apply 属性的 JavaScript 对象。apply 属性会被 webpack 编译器(compiler) 调用。所以webpack 编译器可以在整个编译生命周期使用插件。

使用

之前的示例,浏览器打开index.html,F5频繁刷新可以看到 ‘ I am index.html ’的样式有瞬间的变化。
这是因为style.css中的样式,是在main.js加载后执行时,通过js在head创建<style>标签的方式插入进去的。
此时html元素已经渲染完展示出来。

为避免这种情况,应该在index.html的head中直接使用。这样也节省了加载时间。

安装配置插件
注意:webpack 4+ 推荐 使用 mini-css-extract-plugin 代替 extract-text-webpack-plugin 实现 css分离 、压缩等处理。

npm install -D mini-css-extract-plugin
// webpack.config.js
var path = require('path');
// 加载插件
var MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
    entry: {
        main: './src/index.js'
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].js' // name为entry定义的入口名:main
    },
    module: {
        rules: [
            {
                test: /\.css$/, // 根据正则匹配.css结尾的文件
                use: [ // 配置loader,倒序使用
                    // { loader: 'style-loader' },
                    { loader: MiniCssExtractPlugin.loader },
                    { loader: 'css-loader' }
                ]
            }
        ]
    },
    plugins: [
        // 用 MiniCssExtractPlugin 抽离出 css 文件
        new MiniCssExtractPlugin({
            filename: '[name].css' // name为entry定义的入口名:main
        }),
    ],
}

打包发现dist目录下多了一个被分离出的css文件 main.css
在这里插入图片描述
现在需要修改index.html,手动引入css文件

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" type="text/css" href="./main.css" />
    </head>
    <body>
        <h1>I am index.html</h1>
        <script src="./main.js"></script>
    </body>
</html>

浏览器打开,样式不会闪动。

chunk

关键字

chunk 块,打包过程中被操作的模块文件。

chunk 有两种来源:

  1. 常规的主要是入口生成的,包含入口文件显式指定的所有模块及其依赖项。
  2. 非常规的可能来源于延迟加载的模块。当使用动态导入(懒加载)或使用SplitChunksPlugin插件(分离重复引用的模块)时,可能会出现这种chunk。

查看chunk

入口文件可以配置多个,现在创建一个util.js文件作为另一个入口,创建一个模块module3.js

// src/module3.js
export default () => {
    console.log('this is module3.js')
}

// src/util.js
// 懒加载module3,在页面加载完后加载module3.js模块
window.onload = e => import('./module3.js').then(module => {
    let show = module.default;
    show();
});

// webpack.config.js修改
// ...
module.exports = {
    entry: {
        main: './src/index.js',
        util: './src/util.js'
    },
    // ...
}

打包查看详情,展示了打包生成的4个文件。2.js是
在这里插入图片描述

个人理解:
1.webpack先将入口文件根据依赖关系合并 module
2.生成对应的chunk文件:
css/style.css index.js module1.js module2.js 合并为 chunk0.js
util.js 合并为 chunk1.js
module3.js 合并为 chunk2.js
3.经过处理,输出bundle文件:
chunk0 由于 css分离,输出main.css和mian.js
chunk1 输出 util.js
chunk2 输出 2.js

module chunk bundle

module,chunk 和 bundle 其实就是同一份逻辑代码在不同转换场景下的取了三个名字:
我们直接写出来的是 module,webpack 处理时是 chunk,最后生成浏览器可以直接运行的 bundle。

错误追踪 Source Map

webpack 将 文件 压缩 编译 打包后转换成只有几行的代码,其中的变量名也被改了名字,使用浏览器工具查看报错信息时,根本不知道它的原始位置。

添加一个错误:

// src/module2.js
export var message = 'this is module2';
class Person{
    show() {
        throw new Error('this is a mistake');
        console.log('My name is Jack');
    }
}
let p = new Person;
p.show();

在这里插入图片描述

生成 Source Map 除错工具将直接显示原始代码,而不是转换后的代码,这无疑给开发者带来了很大方便。

Source map 一个信息文件(.map后缀),里面储存着位置信息。转换后的代码的每一个位置,所对应的转换前的位置。

webpack 提供 devtool 配置 Source Mapdevtool详解

开发环境推荐:cheap-module-eval-source-map
生产环境推荐:cheap-module-source-map

// webpack.config.js
// ...
module.exports = {
	devtool: 'cheap-module-eval-source-map',
	// ...
}

打包后查看错误:
在这里插入图片描述

关键字总结

entry 入口,既然要构建依赖关系,就需要知道先从哪些文件(模块)开始递归。默认为 ./src/index.js

output 出口,output配置了打包后的文件输出位置 及 如何命名。默认为 ./dist/main.js

bundle 最终打包后的文件。通常是由多个不同的模块产生,它是已经加载完毕和被编译后的源代码的最终版本。默认为 ./dist/main.js

module 模块,对于webpack来说,所有的资源/文件(.js、.css、.png)都是module。如 概念 所说,webpack为这些模块,构建依赖关系图,最终打包。上面的3个js文件(index module1 module2)都是模块。

loader webpack 自身只理解 JavaScript,要处理js以外的模块(css less vue 图片等),则需要 loader 按需对文件进行预处理或“加载”。将它们转换为webpack可以处理的有效模块(js文件、Dataurl等)。

plugin 插件,目的在于解决 loader 无法实现的其他事。

chunk 打包过程中被操作的模块文件。

参考

under-the-hood/#chunks
面试必备!webpack 中那些易混淆的 5 个知识点
2020年4月大厂腾讯前端面经分享
在webpack中,module、chunk和bundle到底是什么样的存在?
webpack——devtool里的7种SourceMap模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值