webpack5 基础

1. 为什么使用webpack

js文件引入发展历程

  1. 单独在html中引入js文件:文件间存在先后顺序的依赖,管理js引入顺序劳心费力。
  2. 将所有js文件通过工具打包到一个js文件中,通过立即执行函数解决作用域问题,但文件过大,不好管理。
  3. nodeJS 使用的commonJS (export require) 包管理工具,前端不支持:通过工具(browserify、requirejs)转为前端支持的,但是生成的代码不够简洁。
  4. esmodule(export import) 直接前端支持的模块化,但是不是所有浏览器都适配。
  5. webpack 支持commonjs 及 esmodule,还支持其他静态资源的打包。

注意:webpack本身是处理js的依赖关系的,其他资源的打包,需要依赖插件。

2. webpack 安装

环境准备:安装node,会一起安装npm、npx

  1. Node Package Management:包管理工具
  2. Node Package Execute:包执行工具,先去node_modules中找命令

需要的包:webpack webpack-cli  最好不用global全局,给每个项目安装单独的webpack版本好控制

运行:npx webpack 打包

加自定义配置: npx webpack --entry ./src/index.js --mode production

保留及复用配置:新增webpack.config.js文件。

3. webpack.config.js 文件

位置:项目的根目录下

格式:js 文件

作用:设置打包时的配置信息 entry,output,mode,devtool,module,plugins,optimization,performance

const path = require('path')
module.exports = {
    
    entry:'./src/index.js',

    output:{
        filename:'bundle.js',
        path: path.resolve(__dirname,'./dist')
    },

    mode:'none',
}

4. webpack 打包流程

例如,js是依赖的起始,entry文件可以依赖多个文件,层层依赖。

webpack有很多插件,可以进行打包优化、资源管理(图片、文本等资源),利用插件还可以简化使用。

5. webpack 插件

注意:配置在webpack.config.js中的plugins:[{},{}] 中

5.1 html-webpack-plugin

作用:根据配置,将src index.html文件作为模板,生成dist下的新html文件,且自动添加js依赖(dist中打包后的)。

安装:

 npm install  html-webpack-plugin -D

使用:

//引入 返回的是构造函数
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    plugins:[
        new HtmlWebpackPlugin({
            //使用的模板,相对路径
            template:'./index.html',
            //生成的目标文件
            filename:'app.html',
            //js 注册的位置
            inject:'body'
        }),
    ]
}

6 webpack 开发环境搭建

6.1 mode:'development'

使用开发模式。

6.2 devtool:'inline-source-map'

作用:调试时,src下展示源文件。

 配置前:src下是编译后的js文件,跟源码不一致。

配置后:src下是源文件格式。

6.3 npx webpack --watch

作用:监测js变化,自动重新打包,但还是需要刷新页面。

6.4 webpack-dev-server

第三方库,实现热模块更新替换,监测js变化,自动重新打包且刷新页面。

安装:npm install webpack-dev-server -D

配置:webpack.config.js中配置读取的目录。

//配置webpack-dev-server读取的目录
devServer:{
	static:'./dist'
},

7. asset modules 内置资源模块

作用:用来引入其他类型资源,类似图片(png/jpg/svg)以及文本txt

7.1 资源模块类型

资源模块类型即webpack处理资源时,处理方式的类型。

  1. asset/resource  返回资源文件对应的url
  2. asset/inline 返回资源文件的dataUrl base64
  3. asset/source 返回资源的源码,类似txt中的内容,直接import是读不出来的,设置规则可读取txt中的文本内容
  4. asset 自动选择resource还是inline可配置临界值大小。

7.2 模块下配置规则

test&type

module.exports = {
    //入口,相对路径,打包文件的入口
    entry:'./src/index.js',

	//资源模块配置
    module:{
		//配置规则
        rules:[
            {
                //匹配资源的正则表达式
                test:/\.png$/,
                //资源类型  加载资源返回url
                type:'asset/resource',
                //配置打包生成文件的位置及名称
                generator:{
                    // filename:'images/test.png'
                    filename:'images/[contenthash][ext]'
                }
            },

            {
                // asset/inline 行内资源 base64 常用来加载svg
                test:/\.svg$/,
                type:'asset/inline',
            },

            {
                //获取资源的源数据
                test:/\.txt$/,
                type:'asset/source'
            },

            {
                test:/\.jpg$/,
                type:'asset',
                parser:{
                    //什么时候选择dataUrl,设置其对应的最大值
                    dataUrlCondition:{
                        maxSize: 4*1024*4024,
                    }
                }
            }
        ]
    }
}

7.3 引入资源并使用

使用时,直接import 引入

匹配到rules中的规则,webpack会处理加载及使用

如果没有匹配到,又非js/json文件,webpack会报错

import hello  from "./hello";
//引入需要使用到的图片/文字资源,引入了资源,匹配到rules中的规则,webpack会处理加载及使用
//如果没有匹配到,非js,json文件,webpack会报错
import imgsrc from './assets/free.png'
import svgsrc from './assets/folder-svgrepo-com.svg'
import emText from './assets/hello.txt'
import jpgMap from './assets/16627.jpg'

//图片资源设置对应元素的src
const img = document.createElement('img');
img.src = imgsrc;
document.body.appendChild(img)

const img2 = document.createElement('img');
img2.src = svgsrc;
img2.style.cssText = "width:600px;hight:300px";
document.body.appendChild(img2);

//文本资源可用div textContent属性展示
const block = document.createElement('div')
block.textContent = emText;
block.style.cssText = "width:600px;height:400px;background:lightblue";
document.body.appendChild(block)

const img3 = document.createElement('img')
img3.src = jpgMap;
console.log(jpgMap)
img3.style.cssText = "width:1000px;height:800px;display: block"
document.body.appendChild(img3);

asset/inline返回样式,常用来加载svg小图片

8 loader 外部插件/库,加载其他资源

test&use

8.1 加载css、less文件

安装需要依赖的包

npm install style-loader css-loader less-loader less -D

  1. style-loader 负责将css样式加载到页面head中
  2. css-loader 加载css文件
  3. less-loader 加载less文件
  4. less 解析less文件

module中配置

注意use顺序:从右往左,链式调用,逆序执行。

module.exports = {
    //入口,相对路径,打包文件的入口
    entry:'./src/index.js',
    
    module:{
        rules:[
			//加载css或less资源
            {
                test:/\.(css|less)$/,
                use:['style-loader','css-loader','less-loader']
            }
        ]
    }
}

配置css/less样式

引入资源并使用

import './assets/style/hello.css'
import './assets/style/style.less'

document.body.classList.add('hello')
//less中是body元素上添加的样式,加载进来直接生效

加载效果

8.2 抽离css

安装插件:npm install mini-css-extract-plugin -D

config配置:

//抽离css到单独文件 默认main.css
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = {
    //入口,相对路径,打包文件的入口
    entry:'./src/index.js',
	
	//插件配置
	plugins: [
		//使用抽离css插件
		new MiniCssExtractPlugin({
			//指定路径及文件名
			filename: 'style/[contenthash].css'
		}),
	],
    
    module:{
        rules:[
			//加载css或less资源
            {
                test:/\.(css|less)$/,
				//使用抽离css的loader替换style-loader 
                use:['MiniCssExtractPlugin.loader','css-loader','less-loader']
            }
        ]
    }
}

重新打包后结果

app.html,css样式通过link标签引入

生成的css文件

8.3 压缩css

安装插件  npm install css-minimizer-webpack-plugin -D

config配置

//压缩dist中的css文件
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')

module.exports = {
    //入口,相对路径,打包文件的入口
    entry:'./src/index.js',
	
	
	//模式
    mode: 'production',
    
    /**
     * 优化配置,需结合production 模式使用
     */
    optimization: {
        //压缩工具 mode未production时才执行
        minimizer: [
            new CssMinimizerPlugin()
        ]
    }
}

打包后效果:

8.4 样式中使用images

css文件中直接引用图片相对路径即可

/* css中也可以直接使用图片资源,只要配置过图片资源加载方式,webpack就能加载 */
.block-bg {
    background-image: url('../webpack-logo.svg') !important;
}

8.5 加载fonts字体

fonts字体也是资源的一种,用asset/resource加载

下载字体:这里是iconfont

配置config:

module.exports = {
    //入口,相对路径,打包文件的入口
    entry:'./src/index.js',
	    
    module:{
        rules:[
			{
				// 加载字体 icon图标也是字体的一种
				test:/\.(woff|woff2|eot|ttf|otf)$/,
				type:'asset/resource',
			},
        ]
    }
}

CSS中配置字体:

使用字体:

页面效果:

8.6 加载csv/tsv/xml数据

下载loader: npm install csv-loader xml-loader -D

准备数据:

配置config

module.exports = {
    //入口,相对路径,打包文件的入口
    entry:'./src/index.js',
	    
    module:{
        rules:[
			// csv表格
            {
                test:/\.(csv|tsv)$/,
                use:'csv-loader'
            },
            // xml文件
            {
                test:/.\xml$/,
                use:'xml-loader',
            },
        ]
    }
}

使用数据:

//引入数据文件
import csvData from './assets/data.csv'
import xmlData from './assets/data.xml'
//直接输出
console.log(csvData);
console.log(xmlData);

加载结果:

csv数组,xml对象

8.7 自定义json模块parser

作用:加载类json文件

下载第三方库:npm install toml yaml json5 -D

作用解析toml yaml json5文件,且配有loader供webpack使用

准备数据:

配置config文件:

//引入 toml yaml json5
const toml = require('toml')
const yaml = require('yaml')
const json5 = require('json5')

module.exports = {
    //入口,相对路径,打包文件的入口
    entry:'./src/index.js',
	    
    module:{
        rules:[
			 /**
             * 自定义json模块,注意type为'json' 使用toml yaml json5的parse进行转换
             */
            {
                test:/\.toml$/,
				//注意type为'json'
                type:'json',
                parser:{
                    parse:toml.parse
                }
            },
            {
                test:/\.yaml$/,
                type:'json',
                parser:{
                    parse:yaml.parse
                }
            },
            {
                test:/\.json5$/,
                type:'json',
                parser:{
                    parse:json5.parse
                }
            }
        ]
    }
}

使用数据:

//引入数据文件
import yaml from './assets/data.yaml'
import toml from './assets/data.toml'
import json5 from './assets/data.json5'

//webpack直接将json转换为了对象
console.log(toml.title)
console.log(toml.owner.name);

console.log(yaml.title)
console.log(yaml.owner.name);

console.log(json5.title)
console.log(json5.owner.name);

输出结果:

9. babel-loader

webpabk本身能打包js资源,但是不会对ES6语法进行转换,某些浏览器不支持ES6的话,就会报错,所以使用babel进行ES6到ES5的转化。

将hello.js中加入ES6语法,重新打包,查看打包后的文件,发现未转换。

9.1 安装

npm install babel-loader  @babel/core @babel/preset-env -D

  1. babel-loader webpack中解析es6
  2. @babel/core babel核心模块
  3. @babel/preset-env 针对不通的ES6语法(promise,=>,...)有定制对应的插件,preset-env是插件的集合

9.2 配置config

module.exports = {
    //入口,相对路径,打包文件的入口
    entry:'./src/index.js',
	    
    module:{
        rules:[
			{
                test: /\.js$/,
                //正则表达式,包中的js无需解析
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            }
        ]
    }
}

9.3 效果

10 代码分离

项目大了后会有多个js文件,且如果都打包在一个文件中,体积过大,影响页面效率,且有些js文件特定条件下才需要加载,所以需要实现代码分离(多个js文件),按需加载。

10.1 入口文件

通过entry中配置多个文件,实现代码分离。

优点:配置简单

缺点:包不共享,依赖打包了多次,占用体积。

准备文件:

使用lodash包,且一旦被加载,直接输出拼接后的字符串

配置config

module.exports = {
    //入口,相对路径,打包文件的入口
    entry: {
        index: './src/index.js',
        another:'./src/another.js'
    },

    //输出配置
    output: {
        //输出的文件名,这里name会去entry中的key
        filename: '[name].js',
        //输出的路径,这里需要是绝对路径
        path: path.resolve(__dirname, './dist'), 
    },
}

打包结果

此时文件大小:

在index中也使用lodash,重新编译打包,可以看到index也重新打包了lodash

10.2 防止重复

10.2.1 entry 配置dependOn和shared

缺点:依赖关系得手动设定,心智负担重。

配置config

module.exports = {
    //入口配置dependOn&shared
    entry: {
        index: {
            import:'./src/index.js',
            dependOn:'shared',
        },
        another:{
            import:'./src/another.js',
            dependOn:'shared',
        },
        shared:'lodash'
    },
}

打包效果:

10.2.2 SplitChunksPlugin

缺点:无法按需加载。

插件,webpack5自带的,自动分离公共依赖

module.exports = {
	entry: {
        index:'./src/index.js',
        another:'./src/another.js',
	},
    optimization: {
		//分离公共模块
        splitChunks:{
            chunks:'all'
        }
    }
}

打包结果:

10.2.3 动态导入

通过import('包、文件') 实现动态导入

当执行某些操作,可在对应的回调函数中import资源,实现按需加载。

10.3 懒加载

定义math.js

export const add= (x,y)=>{
    return x+y;
}

import导入:index.js 中配置点击按钮时加载math.js

const button = document.createElement('button')
button.innerHTML = '加法计算'
button.addEventListener('click',()=>{
    //动态导入  /*webpackChunkName:'math.js'*/ 指定打包后的文件名
    import(/*webpackChunkName:'math.js'*/'./math.js').then(({add})=>{
        console.log(add(3,5));
    })
})
document.body.appendChild(button);

页面效果:

点击按钮,才加载math.js

10.3.1 懒加载的两种配置

webpack 魔法注释

prefecth:网络空闲时加载,不用非得等到事件触发 推荐

preload:直接跟随主chunk并行下载

button.addEventListener('click',()=>{
    //动态导入  /*webpackChunkName:'math.js'*/ 指定打包后的文件名
    import(/* webpackChunkName: 'math', webpackPrefetch: true */'./math.js').then(({add})=>{
        console.log(add(3,5));
    })
})

网络空闲时直接下载,非点击button才触发

11 缓存

浏览器会将文件缓存下来,减少网络开销,确保自身代码改动时,重新加载,而第三方库使用缓存

11.1 自定义文件

通过定义文件名通过内容生成hash值,当内容改变后,生成新文件名来去缓存

module.exports = {
	entry: {
        index:'./src/index.js',
        another:'./src/another.js',
	},
	output: {
        //输出的文件名,contenthash会根据内容生成hash值
        filename: 'scripts/[name].[contenthash].js',
    },
}

11.2 第三方库

第三方库,打包到一个文件中,配置需缓存。

多个包时,生成多个输出文件

config配置

module.exports = {
	entry: {
        index:'./src/index.js',
        another:'./src/another.js',
	},
	output: {
        //输出的文件名,contenthash会根据内容生成hash值
        filename: '[name].[contenthash].js',
    },
	splitChunks:{
		cacheGroups:{
			vendor:{
				test:/[\\/]node_modules[\\/]/,
				name:'vendors',
				chunks:'all',
			}
		}
	}
}

重新打包后的效果:

12 生成、开发环境分离

12.1 分离配置

输出路径变更

12.2 合并逻辑

npm install webpack-merge -D

通过传入的env决定加载什么配置

const {merge} = require('webpack-merge')
const commonConfig = require('./webpack.config.common')
const devConfig = require('./webpack.config.dev')
const prodConfig = require('./webpack.config.prod')

module.exports = (env)=>{
    switch(true){
        case env.development:
            let outObj = merge(commonConfig,devConfig);
            console.log(JSON.stringify(outObj.output));
            return outObj;
        case env.production:
            return merge(commonConfig,prodConfig);
        default:
            return new Error('No matching config was found')
    }
}

12.3 配置脚本

npm run start/build 执行对应命令

{
  "name": "webpack_base",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "webpack serve -c ./config/webpack.config.js --env development",
    "build":"webpack serve -c ./config/webpack.config.js --env production"
  }
   //...
}
  • 22
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值