前言
- webpack是什么?
- 为什么要使用webpack?
- webpack怎么做的?
本文小柱即自己的理解(在写文章之前,未查阅文章的理解),如果纰漏欢迎指正!
概述
webpack是什么?
小柱曰:Webpack就是一个构建工具,能够将css,js,img等资源整合,压缩的工具
官网曰:webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具
为什么要使用Webpack?
小柱曰:jq时代已经一去不复返,那时也许你还在为找手动压缩css,js而发愁,后来webstrom,subline插件解放了你我的双手
官网曰:在浏览器中运行 JavaScript 有两种方法。第一种方式,引用一些脚本来存放每个功能;此解决方案很难扩展,因为加载太多脚本会导致网络瓶颈。第二种方式,使用一个包含所有项目代码的大型 .js 文件,但是这会导致作用域、文件大小、可读性和可维护性方面的问题。
webpack怎么做的?
单页面文件(index.html)入口资源打包
思考问题如下:
- 如何将多个js,css文件打包合并后放入指定文件夹
- 合并后的js和css文件如何自动写入到单个入口文件index.html中
- 初始化项目,生成package.json文件
npm init
- 初始化打包基本配置webpack.base.config.js,单页名入口public/index.html,多文件:js文件夹下button1.js和button2.js,css文件夹:index.css,common.css, img文件夹:logo.img 3.项目文件目录
4.webapck.base.config.js代码:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: {
button1: "./js/button1.js",
button2: "./js/button2.js",
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name].[chunkhash:8].js",
//[name]文件名,[chunkhash:8]的意思是每次输出在文件后随机生成一个8位数,让文件不一样
},
plugins: [new HtmlWebpackPlugin()],
};
说明:此处entry如果是一个数组entry: ["./js/button1.js","./js/button2.js"],会将两个文件打包合并为一个main.abweerew.js文件输出到dist目录下,index.html引用,此处entry如果是一个对象entry: { button1: "./js/button1.js", button2: "./js/button2.js", },会将两文件分开压缩输出到dist目录下,并在index.html引用
5.package.json代码:
{
"name": "webpack-demo",
"version": "1.0.0",
"description": "webapck 打包",
"scripts": {
"start": "webpack --config webpack.base.config.js"
},
"author": "",
"license": "ISC",
"devDependencies": {
"html-webpack-plugin": "^5.3.2",
"webpack": "^5.52.1",
"webpack-cli": "^4.8.0"
}
}
此处入坑:如果出于某些原因,需要根据特定情况使用不同的配置文件,则可以通过在命令行中使用 --config 标志修改,webpack,webpack-cli两个包如果全局安装无需单独安装,如果全局未安装,可能提示webpack不是内部命令
5.该模块问题思考问题答案:
- 打包合并放入指定文件夹:
output:path: path.resolve(__dirname, "文件夹名") - 打包合并后的文件如何自动在index.html中引入:安装:需要安装插件html-webpack-plugin帮助我们做这些
npm i --save-dev html-webpack-plugin
new HtmlWebpackPlugin({template: '入口文件'}) 入口文件即:'./public/index.html',会在入口文件中引入合并压缩后的css,js代码,然后输入到dist目录下
此处思考遗留问题:如何将压缩后的js代码,和css代码输入到指定文件夹指定目录下,例如即压缩后js代码放入dist/js/XXX.js,dist/css/xxx.css?
google搜索了下:url-loader做了这些事情,接下来去实现发现有问题,继续搜索搜多感觉合理的答案链接:stackoverflow.com/questions/3…
loader作用
小柱曰:webpack不能识别非js结尾的文件,需要用到loader做一个预处理,转换成想要格式
官网曰:(webpack.docschina.org/concepts/lo…)
不同文件类型如何输入到dist不同目录下?
1.js文件打包后放入dist/js文件夹下?output出口处,filename指定输入文件夹/文件名即可
filename: "js/[name].[chunkhash:8].js",
2.css文件打包后放入dist/css文件夹下?
此处发现只引入css各种loader是不能为每个包含 CSS 的 JS 文件创建一个 CSS 文件:
webpack5中:
npm install --save-dev mini-css-extract-plugin
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
传送门[:webpack.docschina.org/plugins/min…]
a.npm install --save-dev css-loader sass-loader scss-loader style-loader node-sass
b.加入css相关loader配置
rules: [{
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
// 将 JS 字符串生成为 style 节点
// "style-loader",
// 将 CSS 转化成 CommonJS 模块
"css-loader",
// 将 Sass 编译成 CSS
"sass-loader",
],
}],
},
c.指定css输入到css文件夹:new MiniCssExtractPlugin({ filename: 'css/[name].[chunkhash:8].css' })
d.webapck.base.config.js代码:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== "production";
module.exports = {
entry: {
button1: "./js/button1.js",
button2: "./js/button2.js",
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "js/[name].[chunkhash:8].js",
//[name]文件名,[chunkhash:8]的意思是每次输出在文件后随机生成一个8位数,让文件不一样
},
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
// 将 JS 字符串生成为 style 节点
// "style-loader",
// 将 CSS 转化成 CommonJS 模块
"css-loader",
// 将 Sass 编译成 CSS
"sass-loader",
],
},
],
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({ template: "./public/index.html" }),
new MiniCssExtractPlugin({
filename: 'css/[name].[chunkhash:8].css'
}),
],
watch: true
};
多页面文件(page1.html,page2.html)入口资源打包
应用场景
每个业务模块有单独的入口,不同的业务模块之前可能有公用的组件库,工具类,但是不同的入口文件负责不同的业务。
配置步骤
1.新建项目目录和项目文件:
2.webpack相关配置:
思考问题:
- 如何将公共的业务js(common.js),公共的模块jquery,react,vue等js(vendor.js),公共的common.scss 分别打包引入两个入口module1/index.html,module2/index.html
- 如何将各自业务模块打包进入,引入进各自的入口文件中
1.多个页面配置entry
2.多页面的 index.html 模板各不相同,所以需要配置多个 HtmlWebpackPlugin。 此处入坑page/module1 和page/module2 下的入口文件不要叫相同的index.html
- 配置抽离公共业务代码(以抽离公共common.js做示例),公共第三方库js(以抽离第三方jquery库做示例) 4.webapck.base.config.js代码:
const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// const CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin; 改插件webpack5已经被移除掉了,取而代之optimization.splitChunks
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const devMode = process.env.NODE_ENV !== "production";
module.exports = {
entry: {
module1: "./js/entry1.js",
module2: "./js/entry2.js",
// common: ["./js/common.js"],
// vendors: ['jQuery'],
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "js/[name].[chunkhash:8].js",
//[name]文件名,[chunkhash:8]的意思是每次输出在文件后随机生成一个8位数,让文件不一样
},
// externals: {
// jquery: 'jQuery',
// },
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
// 将 JS 字符串生成为 style 节点
// "style-loader",
// 将 CSS 转化成 CommonJS 模块
"css-loader",
// 将 Sass 编译成 CSS
"sass-loader",
],
},
{
test: require.resolve("jquery"),
loader: "expose-loader",
options: {
exposes: ["$", "jQuery"],
},
},
],
},
plugins: [
// new BundleAnalyzerPlugin(),
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: "module1",
filename: "module1.html",
chunks: ["module1","vendors"],
template: "./page/module1/module1.html",
}),
new HtmlWebpackPlugin({
title: "module2",
filename: "module2.html",
chunks: ["module2"],
template: "./page/module2/module2.html",
}),
// 抽离css插件
new MiniCssExtractPlugin({
filename: "css/[name].[chunkhash:8].css",
}),
],
// 抽离,切割公共组件插件
optimization: {
splitChunks: {
cacheGroups: {
// 打包第三方库的文件
vendors: {
name: "vendors",
test: /[\\/]node_modules[\\/](jquery)[\\/]/,
chunks: "all",
priority: 10,
minChunks: 1, // 同时引用了 2 次才打包
},
// 打包业务中公共代码
common: {
name: "common",
chunks: "initial",
minSize: 1,
priority: 0,
minChunks: 2, // 同时引用了 2 次才打包
},
},
},
runtimeChunk: { name: "manifest" },
},
watch: true,
};
总结
代码github代码传送门:git@github.com:zhuzi002/webpack.git 小白容易踩坑的点:
- MiniCssExtractPlugin.loader插件的使用一般只用于生产环境,style-loader一般用于开发环境,下一篇文章会讲述不同环境开发配置,打包相关配置,
- 多页面入口中安装第三方插件,例如jquery,允许暴露一个模块(整体或者部分)给全局对象,需要配置expose-loader
- 【重点】,抽离第三方组件库时,vendors中要配置对应抽离的组件库规则,规则不要配置错,假设我只抽离jquery这个组件库,minChunks:1,不能配置为minChunks:2,common中要配置抽离公共业务组件的规则