IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> webpack 学习笔记 -> 正文阅读

[JavaScript知识库]webpack 学习笔记

一、Webpack 的构建流程主要有哪些环节?如果可以请尽可能详尽的描述 Webpack 打包的整个过程

1、初始化项目,初始化参数:根据用户配置的不同参数
2、初始化参数,根据用户在命令窗输入的参数,以及 webpack.config.js 的配置,得到最后的配置
3、开始编译,根据上一步得到的最后的配置参数,初始化得到一个 compiler 对象,注册所有的插件 plugin ,插件开始监听 webpack 的构建过 程,
不同的环节会对应相应的处理然后开始执行编译。
3、确定入口,根据 webpack.config.js 中的 entry 入口,开始解析文件构建 AST 语法树,找出依赖递归下去。
4、编译模块,在递归过程中,根据文件类型和 loader 配置,调用相应的 loader 对不同的文件进行不同的转换处理。再找出该模块依赖的模块,
直到项目中依赖的所有模块都经历过编译处理
5、完成编译并输出、递归结束后,得到每个文件结果,包含转换后的模块及他们之间的依赖关系,根据 entry 以及 output 等配置生成代码块,
会在结束之前清楚 dist 目录。
6、打包完成、根据 output 输出到指定目录。

2、Loader 和 Plugin 有哪些不同?请描述一下开发 Loader 和 Plugin 的思路。

一、Loader 直译为 “加载器”,主要是用来解析和检测对应资源,负责源文件从输入到输出的转换,他专注于实现资源模块的加载。
将一些浏览器不支持或者兼容有问题的代码,处理为浏览器可以支持的资源。如:将 ES6+ 转换为浏览器可以识别的 ES5、Sass 转换为 css。
1、通过 moudule.exports 导出一个函数
2、该函数默认参数 第一个参数 source (即要处理的资源文件)
3、在函数体中处理资源(Loder 里配置响应的 Loder 后)
4、通过 return 返回最后打包的结果(这里返回的结果需要为字符串格式)

二、Plugin 主要在 webpack 构建的不同阶段执行一些额外的工作,比如拷贝静态资源、清空打包后的文件夹等。
1、通过钩子机制实现
2、插件必须是一个函数,或者包含 apply 方法的对象
3、在方法体内通过 webpack 提供的 API 获取资源做响应处理
4、将处理完的资源通过 webpack 提供的方法返回给该资源

## webpack.common.js

// const path = require('path')
const resolveApp = require('./paths')
const HtmlWebpackPlugin = require('html-webpack-plugin')  // 打包是自动创建自动创建 html
const TerserPlugin = require("terser-webpack-plugin")  // 代码拆分加载打包去除不必要文件
const { merge } = require('webpack-merge')
const MiniCssExtractPlugin = require("mini-css-extract-plugin")

// 时间分析
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin")
const smp = new SpeedMeasurePlugin()

// 导入其他的配置
const prodConfig = require('./webpack.dev')
const devConfig = require('./webpack.dev')

// 定义对象保存 base 配置信息
const commonConfig = {
	entry: './src/main.js',  // 编译目标资源文件
	devtool: 'source-map',  // 代码映射,定位报错位置
	// inline 列报错,cheap 提高效率去掉空行。cheap-module 原本还原。
	resolve: {
		extensions: [".js", ".json", ".ts", ".jsx", ".vue"],  // 匹配路由后面的路径,省略文件格式后缀
		alias: {
			// '@': path.resolve(__dirname, '../src')  // 匹配路由后面的路径,省略路径前面的 ./
			'@': resolveApp('./src')
		}
	},
	output: {
		filename: 'js/build.js', // 输出文件名 并且单独放到 js 目录下
		// filename: 'js/[name].build.js',  // 代码拆分打包,动态文件名
		// path.resolve(__dirname, '../dist'), // 输出文件夹
		path: resolveApp('./dist'),
		publicPath: '/lg'  // 相对路径或者绝对路径,地址目录
	},
	externals: {  // 引入CDN
		lodash: '_'  //  引入后的命名
	},
	optimization: {
		minimizer: [
			new TerserPlugin({
				extractComments: false,
			}),
		],
		splitChunks: {
			chunks: 'all',  // 支持异步和同步 all
			minSize: 20000,  // 文件大小
			maxSize: 20000,
			minChunks: 1,
			cacheGroups: {
				syVendors: {
					test: /[\\/]node_modules[\\/]/,
					filename: 'js/[id]_vendor.js',  // filename 可以动态,name 只能写死
					priority: -10,
				},
				default: {  // 访问次数
					minChunks: 2,
					filename: 'js/syy_[id].js',
					priority: -20,
				}
			}
		}
	},
	module: {  // 资源模块
		rules: [  // 规则
			{
				test: /\.css$/,
				use: [
					'style-loader',
					{
						loader: 'css-loader',
						options: {
							// postcss-loader 没有检查出需要兼容的代码,被 css-loader 检查出来,可以回退一步
							importLoaders: 1
						}
					},
					{
						loader: 'postcss-loader',  // js转换样式工具。需要安装 postcss 和 postcss-cli
						options: {  // 配置参数
							postcssOptions: {
								plugins: [  // 需要的插件
									require('autoprefixer'),
									require('postcss-preset-env')  // 处理 css 兼容问题,包括 autoprefixer 在内
								]
							}
						}
					},
					{
						test: /\.(png|svg|gif|jpe?g)$/,  // 处理图片
						// use: [
						// 	{
						// 		loader: 'file-loader',
						// 		options: {
						// 			name: 'img/[name].[hash:6].[ext]',  // 给图片规定路径和命名(路径/名字.哈西6位.后缀
						// 			limit: 25 * 1024  // 图片大小
						// 		}
						// 	}
						// ]
						type: 'asset',
						generator: {
							filename: 'img/[name].[hash:6].[ext]'
						},
						parser: {  // 解析
							dataUrlCondition: {
								maxSize: 30 * 1024
							}
						}
					},
					{
						test: /\.(ttf|woff2?)$/,  // 处理字体
						type: 'asset/resource',
						generator: {
							filename: 'font/[name].[hash:3][ext]'
						}
					}
				]
			},
			{
				test: /\.less$/,
				use: [
					'style-loader',
					'css-loader',
					'postcss-loader',  // 原理同上,外部调用 postcss-loader 文件
					'less-loader'
				]
			},
			{
				test: /\.js$/,  // 使用 bable-loader 用来转换 es6 语法
				use: ['bable-loader']
			},
			{
				test: /\.jsx?$/,  // react 热更新
				use: ['babel-loader']
			},
			{
				test: /\.vue$/, // vue 热更新
				use: ['vue-loader']
			},
			{
				test: /\.ts$/,
				use: ['bable-loader']
			},
			{
				test: /\.css$/,  // 抽离 css
				use: [
					isProduction ? MiniCssExtractPlugin.loader : 'style-loader',
					{
						loader: 'css-loader',
						options: {
							importLoaders: 1,
							esModule: false
						}
					},
					'postcss-loader'
				]
			},
		]
	},
	plugins: [  // 插件
		new HtmlWebpackPlugin({
			title: 'html-webpack-plugin',  // html 内部 title
			template: './public/index.html'  // html 的模板路径
		})
	]
}

module.exports = (env) => {
	const isProduction = env.Production

	process.env.NODE_ENV = isProduction ? 'prodConfig' : 'development'

	// 根据当前的打包模式来合并配置
	const config = isProduction ? prodConfig : devConfig

	const mergeConfig = merge(commonConfig, config)

	return mergeConfig

	return smp.wrap(mergeConfig)
}



## webpack.dev.js
const VueLoaderPlugin = require('vue-loader/lib/plugin')

module.exports = {
   mode: 'development', // 开发环境
   devtool: 'cheap-module-source-map',  // 代码映射,定位报错位置
   // inline 列报错,cheap 提高效率去掉空行。cheap-module 原本还原。
   target: 'web',  // 屏蔽浏览器兼容
   devServer: {  // 与 webpack dev serve 相关的配置,写在这里
       hot: true,  // 开启热更新
       publicPath: '/lg',  // 和output中的publicPath一致,查找资源目标
       contentBase: path.resolve(__dirname, 'public'),
       watchContentBase: true,
       hotOnly: true,  // 刷新之前的报错(一个组件不被别的组件所影响)
       port: 4000,  // 端口
       open: false,  // 打开一个新页面
       compress: true,  // 对当前文件进行压缩处理
       historyApiFallback: true,  // 路由切换 404
       proxy: {  // 解决跨域
           '/api': {
               target: 'https://api.github.com',  // 问谁要
               pathRewrite: { "^/api": "" },
               changeOrigin: true
           }
       }
   },
   plugins: [  // 插件
 	  new VueLoaderPlugin()
   ]
}



## 标题webpack.prod

const { CleanWebpackPlugin } = require('clean-webpack-plugin')  // 清楚 dist 插件
const CopyWebpackPlugin = require('copy-webpack-plugin')  // 拷贝
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin")
const TerserPlugin = require("terser-webpack-plugin")  // 压缩 js
// const webpack = require('webpack')
const PurgeCSSPlugin = require('purgecss-webpack-plugin')
const resolveApp = require('./paths')
const glob = require('glob')
const CompressionPlugin = require("compression-webpack-plugin")  // 压缩资源
const InlineChunkHtmlPlugin = require('inline-chunk-html-plugin')  // 注入 js 代码
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
	mode: 'production', // 生产环境
	optimization: {
		// usedExports: true,  // 标记代码执行 (把代码中不被使用到的内容进行标记)
    	minimize: true,
		minimizer: [
			new CssMinimizerPlugin(),
			new TerserPlugin({
				extractComments: false
			})
		]
	},
	plugins: [  // 插件
		new CleanWebpackPlugin(),  // 清除 dist
		new CopyWebpackPlugin({
			patterns: [  // 
				{
					from: 'public',  // 从哪开始进行拷贝,目标目录。 可以省略 to ,默认去找 output 下面的 path 目录
					globOptions: {  // 忽略某些内容
						ignore: ['**/index.html']  //  **/ 表示从 public 下去寻找
					}
				}
			]
		}),
		// new webpack.optimize.ModuleConcatenationPlugin()
		new PurgeCSSPlugin({
			paths: glob.sync(`${resolveApp('./src')}/**/*`, { nodir: true }),  // 保留文件去掉目录
			safelist: function () {
			  return {
				standard: ['body', 'html', 'ef']
			  }
			}
		}),
		new CompressionPlugin({
			test: /\.(css|js)$/,
			minRatio: 0.8,
			threshold: 0,  // 体积大于 0 开始压缩
			algorithm: 'gzip'  // 浏览器支持的压缩算法
		}),
		new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime.*\.js/])  // 把 js 代码注入 html
	]
}


## paths.js

// 路径模块 
// 依据当前config目录去查找
const path = require('path')

const appDir = process.cwd()

console.log(appDir, '<---')

const resolveApp = (relativePath) => {
    return path.resolve(appDir, relativePath)
}

module.exports = resolveApp



## babel.config.js

// bable的配置 用来转换 js 代码
// module.exports = {
//     presets: [
//         '@babel/preset-env',
//         {  // polyfill 填充 babel 功能不够的插件
//             // false: 不对当前的 js 处理做 polyfill 的填充
//             // usage: 依据用户的源代码当中作使用到的新语法进行填充
//             // entry: 依据当前筛选出来的浏览器决定填充什么
//             useBuiltIns: 'entry',
//             corejs: 3  // corejs 版本为 3
//         }
//     ]
// }

const presets = [
    [
        '@babel/preset-env',
        {  // polyfill 填充 babel 功能不够的插件
            // false: 不对当前的 js 处理做 polyfill 的填充
            // usage: 依据用户的源代码当中作使用到的新语法进行填充
            // entry: 依据当前筛选出来的浏览器决定填充什么
            useBuiltIns: 'entry',
            corejs: 3  // corejs 版本为 3
        }
    ],
    [ '@babel/preset-react' ]
]

const plugins = []

console.log(process.env.NODE_ENV, '<-----')

// 根据当前的打包模式来决定 plugins 的值
const isProduction = process.env.NODE_ENV === 'production'
if (!isProduction) {
    plugins.push(['react-refresh/babel'])
}

module.exports = {
    presets,
    plugins
}


## postcss.config.js

module.exports = {
    plugins: [
        require('postcss-preset-env')
    ]
}


## Server.js
const express = require('express')
const webpackDevMiddleware = require('webpack-dev-middleware')
const webpack = require('webpack')

const app = express()

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

app.use(webpackDevMiddleware(compiler))

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

// 运行?
// node .\Server.js


## .browserslistr

> 1%
last 2 version
not dead


## babel.config.js

module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        userBuilIns: 'usage',  // 代码插件补全
        corejs: 3  // 版本
      }
    ],
    ['@vue/cli-plugin-babel/preset']
  ]
}



## package.js

{
  "name": "vue-app-base",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "webpack serve --config ./config/webpack.common.js --env development",
    "build": "webpack --config ./config/webpack.common.js --env production",
    "ck": "tsc --noEmit",
    "lint": "npm run serve"
  },

  "sideEffects": [
    "./src/title.js"
  ],
  "dependencies": {  
    "core-js": "^3.6.5",
    "vue": "^2.6.11"
  },
  "devDependencies": {},
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "eslint:recommended"
    ],
    "parserOptions": {
      "parser": "babel-eslint"
    },
    "rules": {}
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead"
  ],
  "description": "1. 这是一个使用 Vue CLI 创建出来的 Vue 项目基础结构\r 2. 有所不同的是这里我移除掉了 vue-cli-service(包含 webpack 等工具的黑盒工具)\r 3. 这里的要求就是直接使用 webpack 以及你所了解的周边工具、Loader、Plugin 还原这个项目的打包任务\r 4. 尽可能的使用上所有你了解到的功能和特性",
  "main": "babel.config.js",
  "keywords": [],
  "author": "",
  "license": "ISC"
}


## .eslintrc.js

// eslint-loader配置在开发环境
const  commonConfig =  require('./webpack.common')
const merge = require('webpack-merge')
const path = require('path')


module.exports = merge(commonConfig,{
    mode:'development',
    devtool:'cheap-module-eval-source-map',
    module:{
        rules:[
            {
                test: /\.js$/, 
                exclude: /node_modules/, 
                use: 'eslint-loader',
                enforce:'pre'
              },
        ]
    },
    devServer: {
        contentBase: path.join(__dirname, 'dist'),
        port: 9000,
        hot: true
    }
})
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-02 14:34:58  更:2021-10-02 14:35:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:12:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码