webpack学习笔记

webpack

  • [webpack中文网]: https://doc.webpack-china.org/

webpack简介

webpak是什么

Webpack是一个模块打包器(bundler)。

在Webpack看来, 前端的所有资源文件(js/json/css/img/less/…)都会作为模块处理
它将根据模块的依赖关系进行静态分析,生成对应的静态资源

webpack五个核心概念

​ Entry 入口(Entry)指示 webpack 以哪个文件为入口起点开始打包,分析构建内部依赖图。

Output 输出(Output)指示 webpack 打包后的资源 bundles 输出到哪里去,以及如何命名

Loader Loader 让 webpack 能够去处理那些非 JavaScript 文件 (webpack 自身只理解JavaScript)

Plugins 插件(Plugins)可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量等。

Mode 模式(Mode)指示 webpack 使用相应模式的配置。

–Mode=development // 开发环境

–mode=production // 生产环境

快速上手

初始化设置
全局安装 npm install webpack webpack-cli -g 
项目安装 npm install webpack webpack-cli -D
创建文件
|- build----------构建生成的文件所在的文件夹
|- src------------源码文件夹   
    |- js---------------js源文件夹
    |- css--------------css源文件夹	
    |- index.js-----入口文件
|- webpack.config.js-----webpack配置文件
|- package.json---项目包配置文件

webpack.config.js
    // resolve用来拼接绝对路径的方法
    const { resolve } = require('path');

module.exports = {
		// webpack配置
		// 入口起点
entry: './src/index.js',
		// 输出
output: {
		// 输出文件名
filename: 'built.js',
		// 输出路径
		// __dirname nodejs的变量,代表当前文件的目录绝对路径
path: resolve(__dirname, 'build')
},
		// loader的配置 
module: {
rules: [
		// 详细loader配置
		// 不同文件必须配置不同loader处理
{		// 排除某些文件(exclude)
		// 匹配哪些文件
test: /\.css$/,
		// 使用哪些loader进行处理
use: [
		// use数组中loader执行顺序:从右到左,从下到上 依次执行
		// 创建style标签,将js中的样式资源插入进行,添加到head中生效
'style-loader',
		// 将css文件变成commonjs模块加载js中,里面内容是样式字符串
'css-loader'
]
}
]
},
		// plugins的配置 
plugins: [
		// 详细plugins的配置
],
		// 模式
mode: 'development', // 开发模式
// mode: 'production'
}

// 运行指令: webpack
运行指令
开发环境
	webpack webpack src/js/index.js -o build/js/built.js --mode=development
	// 功能:webpack 能够编译打包 js 和 json 文件,并且能将 es6 的模块化语法转换成浏览器能识别的语法。
生产环境
	webpack src/js/index.js -o build/js/built.js --mode=production
	// 功能:在开发配置功能上多一个功能,压缩代码。
结论
webpack 能够编译打包 js 和 json 文件。
能将 es6 的模块化语法转换成浏览器能识别的语法。能压缩代码。

问题
	不能编译打包 css、img 等文件。不能将 js 的 es6 基本语法转化为 es5 以下语法。

插件plugins

  • 第一步下载插件 :

    npm install --save-dev html-webpack-plugin

  • 第二步引入插件:

    const htmlWebpackPlugins = require(‘html-webpack-plugin’)

  • 第三步调用插件

    plugins: [

    ​ // plugins配置

    ​ new htmlWebpackPlugins ({

    ​ template:’./src/index.html’

    ​ })
    ]

常用loader

css/less
css-loader 
// 将css文件变成commonjs模块加载js中,里面内容是样式字符串
style-loader
// 创建style标签,将js中的样式资源插入进行,添加到head中生效
less-loader
// 编译less 还需要下载less模块

打包图片资源
打包css中的图片资源
	下载loader包
npm install --save-dev url-loader file-loader
	loader设置
{
 // css加载图片资源配置
test: /\.(jpg|png|gif)$/,
use: [{
     loader: 'url-loader',
     options: {
         // 图片大小小于8kb,就会被base6  处理
      limit: 8 * 1024,
         // 关闭url-loader的es6模块化,使用commonjs解析
      sModule: false,
         // 给图片进行重命名
         // [hash:10]取图片的hash的前10位
         // [ext]取文件原来扩展名
      name: '[hash:10].[ext]'
        }
    }]
}


打包html中的图片资源
	// 下载loader包
npm install --save-dev html-loader
	// loader设置
test:\/.html$\,
use:[{loader: 'html-loader'}]
其他资源打包
在loader中匹配其他资源
	exclude:/\.(html|js|css|...)/    // 取反
loader: 'file-loader',

devserver

devserver是用来自动化(自动编译,自动打开浏览器,自动刷新)
每次执行只会在内存中打包,不会有任何输出结果

安装:
npm install webpack-dev-server

配置
devServer:{
	// 项目构建后的路径
    contentBase: resolve(__dirname,'build'),
    // 启动gzip压缩
    compress:true,
    // 端口号
    port:3000,
    // 自动打开浏览器
    open:true
}

运行指令
	npx webpack-dev-server

css集成兼容压缩处理

提取css成单独文件
下载插件
npm install --save-dev mini-css-extract-plugin
	// 引入插件
MiniCssExtractPlugin = require('mini-css-extract-plugin');
	// 在loader中配置插件的loader方法('style-loader'可以去掉)
use: [
         miniCssExtractPlugin.loader,
         'css-loader'
	 ]
	// plugin配置
new MiniCssExtractPlugin({
	filename: 'css/built.css'
})
css兼容处理
安装loader
npm install --save-dev postcss-loader postcss-preset-env

// 设置nodejs环境变量 (这个变量表示css兼容以开发环境处理)
process.env.NODE_ENV = 'development';

// loader设置
{ 
    loader: 'postcss-loader', 
    options: { ident: 'postcss', plugins: () => [ 
    // postcss的插件
    require('postcss-preset-env')()
    ]}
}

// package.json设置css兼容的规范选项
"browserslist": {
	"development": [
	"last 1 chrome version",
	"last 1 firefox version",
	"last 1 safari version"
],
	"production": [
	">0.2%",
	"not dead",
	"not op_mini all"
]
}

css压缩
安装插件
npm install --save-dev optimize-css-assets-webpack-plugin

引入插件
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin' )

插件调用
plugins:[
	new OptimizeCssAssetsWebpackPlugin()
]

js处理

js语法检测
下载安装包
npm install --save-dev eslint-loader eslint eslint-config-airbnb-base eslint-plugin-import

// loader配置
{
	test: /\.js$/,
	exclude: /node_modules/,
	loader: 'eslint-loader',
	options: {
	// 自动修复 eslint 的错误
	fix: true
}

// package.json配置

"eslintConfig": {
	"extends": "airbnb-base",
	"env": {
		"browser": true
	}
}
js兼容性处理
下载安装包
npm install --save-dev babel-loader @babel/core @babel/preset-env @babel/polyfill core-js

// loader配置
{
	test: /\.js$/,
	exclude: /node_modules/,
	loader: 'babel-loader',
	options: {
		presets:[
		['@babel/preset-env',
			{
				// 按需加载
			useBuiltIns: 'usage',
				// 指定 core-js 版本
			corejs: {
				version: 3
			},
				// 指定兼容性做到哪个版本浏览器
			targets: {
				chrome: '60',
				firefox: '60',
				ie: '9',
				safari: '10',
				edge: '17'
				}
			}
			]
		]
	}
}
js与html压缩
// 生产环境下会自动压缩 js 代码
mode: 'production'

// 压缩html代码使用 HtmlWebpackPlugin插件
new HtmlWebpackPlugin({
	template: './src/index.html',
		// 压缩 html 代码
	minify: {
		// 移除空格
	collapseWhitespace: true,
		// 移除注释
	removeComments: true
	}
})

webpack 优化配置

HMR

​ HMR(模块热替换): 当一个模块发生变化,只会打包这一个模块(而不是打包所有代码) 极大提升构建速度

安装:
npm install webpack-dev-server

html文件默认不使用HMR功能

样式文件处理用style-loader可以使用HMR功能

js代码需要修改代码添加HMR功能

devServer: {
	contentBase: resolve(__dirname, 'build'),
	compress: true,
	port: 3000,
	open: true,
	// 开启 HMR 功能
	hot: true
}

// 监听hot
if(module.hot){
// 一旦module.hot为true,说明开启了HRM功能
module.hot.accept('./add.js',function(){
	//方法会监听add.js文件的变化,一旦发生变化,其他模块不会重新打包构建
	// 而是执行后面的回调函数
	add();
})
}
source-map

​ source-map: 一种提供源代码到构建后代码映射技术 (如果构建后代码出错了,通过映射可以追踪源代码错误)

source-map无需安装下载直接再config.js中调用

devtool: 'source-map'
oneof

oneof: 优化成产打包速度,在oneof内的文件只匹配一次loader

rules:[
{
  test: /\.js$/,
  exclude: /node_modules/,
  	 // 优先执行
  enforce: 'pre',
     use: [{
     loader: 'eslint-loader',
           options: {
               fix: true
                }
      }]
},
{
oneof:[...] // ...moreLoader
}
]
缓存
bebal缓存
// bebal-loader
options:{
	// 开启缓存
	cacheDirectory: true
}

文件资源缓存
hash:每次webpack构建是会生成一个唯一的hash值

chunkhash:根据chunk成成的hash值,如果来源于同一个chunk那么hash值就一样

contenthash:根据文件内容成产的hash,不同文件的hash值一定不一样
tree shaking
tree shaking 去除无用代码
前提 1.使用ES6模块化  2.开启production环境

有可能出现去除css的情况
// 在package中配置
{
	"sideEffects":["*.css","*.less"]
}

code split

split 将文件拆分成多个文件

方法1 多入口文文件
entry:{
	index:'./src/js/index.js',
	test:'./src/hs/test.js'
},
outout:{
	// [name]:取文件名
filename: 'js/[name].[contenthash:10].js',
path: resolve(__dirname, 'build')
}

// config.js配置
// 会将公共的文件单独打包一个chunk
optimization: {
    splitChunks: {
          chunks: 'all'
     }
}

方法2 通过js代码,让某个文件单独打成一个chunk

// import动态导入语法,能将文件单独打包
import(/*webpackChunkName:'test'*/'.test')
	.then(({add})=>{
		add(1,2)
	})
	.catch(()=>{
		console.log('err')
	})

懒加载和预加载

懒加载  当文件需要使用的时候才加载
// import作为callback
import(/*webpackChunkName:'test'*/'.test').then()

预加载  等其他资源加载完毕后才加载
import(/*webpackChunkName:'test,webpackPrefetch:true	'*/'.test').then()

多进程打包

下载安装
npm install --save-dev thread-loader

/*
开启多进程打包。
进程启动大概为 600ms,进程通信也有开销。
只有工作消耗时间比较长,才需要多进程打包
*/

use: [
{
loader: 'thread-loader',
options: {
workers: 2 // 进程 2 个
}
},{
// ...more
}
]

externals

externals可以拒绝打包通过cdn引用的库

// config.js
externals: {
// 拒绝 jQuery 被打包进来
jquery: 'jQuery'
}

dll

使用dll技术,对某些库(jquery,vue)进行单独打包

// 创建新的文件 webpack.dll.js
// webpack.dll.js 配置

// resolve用来拼接绝对路径的方法
const { resolve } = require('path');
// webpack自带插件
const webpack = require('webpack')

const dll = {
	entry:{
		// 最终打包生成的[name]
		jquery:['jquery']
	},
	output:{
		filename:'[name].js',
		path: resolve(__dirname, 'dll'),
		library:'[name]_[hash]' // 打包库向外暴露的内容叫什么名字
	},
	plugins:[
			// 打包生成一个manifest.json 提供和jquery映射
		new webpack.DllPlugin({
				// 映射库暴露的内容名称
			name:'[name]_[hash]',
				// 输出文件路径
			path:resolve(__dirname,'dll/manifest.json')
		})
	],
	mode:'production'
} 

// 运行文件
webpack --config webpack.dll.js
完成上面的步骤后回到config.js
// config.js

// 下载一个新的插件
npm i add-asset-html-webpack-plugin -D

const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');

// webpack自带插件
const webpack = require('webpack')


plugins:[
		// 告诉webpack哪些库不参与打包
	new webpack.DllReferencePlugin({
		manifest:resolve(__dirname,'dll/manifest.json')
	}),
		// 将某个文件打包输出去,并在 html 中自动引入该资源
	new AddAssetHtmlWebpackPlugin({
	filepath: resolve(__dirname, 'dll/jquery.js')
	})
]

webpack 配置详情

output
output: {
// 文件名称(指定名称+目录)
filename: 'js/[name].js',
// 输出文件目录(将来所有资源输出的公共目录)
path: resolve(__dirname, 'build'),
// 所有资源引入公共路径前缀 --> 'imgs/a.jpg' --> '/imgs/a.jpg'
publicPath: '/',
chunkFilename: 'js/[name]_chunk.js', // 非入口 chunk 的名称
// library: '[name]', // 整个库向外暴露的变量名
// libraryTarget: 'window' // 变量名添加到哪个上 browser
// libraryTarget: 'global' // 变量名添加到哪个上 node
// libraryTarget: 'commonjs'
}
module
module: {
rules: [
		// loader 的配置
		{
		test: /\.css$/,
			// 多个 loader 用 use
		use: ['style-loader', 'css-loader']
		},
	{
		test: /\.js$/,
		// 排除 node_modules 下的 js 文件
		exclude: /node_modules/,
		// 只检查 src 下的 js 文件
		include: resolve(__dirname, 'src'),
		// 优先执行
		enforce: 'pre',
		// 延后执行
		// enforce: 'post',
		// 单个 loader 用 loader
		loader: 'eslint-loader',
		options: {}
		},
		{
		// 以下配置只会生效一个
		oneOf: []
	}
]
}
resolve
// 解析模块的规则
resolve: {
// 配置解析模块路径别名: 优点简写路径 缺点路径没有提示
alias: {
$css: resolve(__dirname, 'src/css')
},
// 配置省略文件路径的后缀名
extensions: ['.js', '.json', '.jsx', '.css'],
// 告诉 webpack 解析模块是去找哪个目录
modules: [resolve(__dirname, '../../node_modules'), 'node_modules']
}
devserver
devServer: {
// 运行代码的目录
contentBase: resolve(__dirname, 'build'),
// 监视 contentBase 目录下的所有文件,一旦文件变化就会 reload
watchContentBase: true,
watchOptions: {
// 忽略文件
ignored: /node_modules/
},
// 启动 gzip 压缩
compress: true,
// 端口号
port: 5000,
// 域名
host: 'localhost',
// 自动打开浏览器
open: true,
// 开启 HMR 功能
hot: true,
// 不要显示启动服务器日志信息
clientLogLevel: 'none',
// 除了一些基本启动信息以外,其他内容都不要显示
quiet: true,
// 如果出错了,不要全屏提示~
overlay: false,
// 服务器代理 --> 解决开发环境跨域问题
proxy: {
// 一旦 devServer(5000)服务器接受到 /api/xxx 的请求,就会把请求转发到另外一个服务器
(3000)
'/api': {
target: 'http://localhost:3000',
// 发送请求时,请求路径重写:将 /api/xxx --> /xxx (去掉/api)
pathRewrite: {
'^/api': ''
}
}
}
}
optimization
optimization: {
splitChunks: {
chunks: 'all'
},
// 将当前模块的记录其他模块的 hash 单独打包为一个文件 runtime
// 解决:修改 a 文件导致 b 文件的 contenthash 变化
runtimeChunk: {
name: entrypoint => `runtime-${entrypoint.name}`
},
minimizer: [
// 配置生产环境的压缩方案:js 和 css
new TerserWebpackPlugin({
// 开启缓存
cache: true,
// 开启多进程打包
parallel: true,
// 启动 source-map
sourceMap: true
})
]
}

问题

开发中所有样式文件合并在一个文件还是分离多个文件?

如何管理多个html文件

生产环境最终应该提交什么样的代码

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值