1.什么是webpack?
webpack是一个现代JavaScript应用程序的静态模块打包工具。当webpack处理应用程序时,它会在内部构建一个依赖图(dependency graph),此依赖图会映射项目所需的每个模块,并生成一个或多个bundle包!webpack本身是基于node.js开发的!
官网:https://webpack.docschina.org/
2.为啥要使用webpack?
代码转换:TypeScript编译成JavaScript、LESS/SCSS编译成CSS、ES6/7编译为ES5、虚拟DOM编译为真实的DOM等等…
文件优化:压缩JS、CSS、HTML代码,压缩合并图片,图片BASE64等
代码分割:提取多个页面的公共代码、提取首屏不需要执行部分的代码等
模块合并:在采用模块化的项目里会有很多个模块和文件,需要构建功能把模块分类合并成一个文件
自动刷新:监听本地源代码的变化,自动重新构建、刷新浏览器
代码校验:Eslint代码规范校验和检测、单元测试等
自动发布:自动构建出线上发布代码并传输给发布系统
……
扩展:模块化的发展史:
单例设计模式(Singleton Pattern)
AMD (Asynchronous Module Definition 异步模块定义)
CMD (Common Module Definition 通用模块定义)
CommonJS(一般应用于服务器开发,例如:Node.js)
ES6 Module (ESM : JS官方标准模块定义方式)
https://es6.ruanyifeng.com/#docs/module
……
3.webpack的基础操作
安装
// 为防止全局安装webpack导致版本冲突,真实项目中以本地安装为主
$ npm init -y
$ npm install webpack webpack-cli --save-dev
OR
$ yarn add webpack webpack-cli -D
零配置使用
/*
* 默认会打包SRC目录中的JS文件(入口默认index.js)
* 打包完成的目录默认是DIST/MAIN.JS
* webpack默认支持CommonJS和ES6 Module的模块规范,依此进行依赖打包
*/
$ npx webpack
自定义基础配置
webpack.config.js OR webpackfile.js
let path = require('path');
module.exports = {
//=>打包模式 开发环境development 生产环境production
mode: 'production',
//=>入口
entry: './src/index.js',
//=>输出
output: {
//=>输出文件的文件名
filename: 'bundle.js',
//=>输出目录的"绝对路径"
path: path.resolve(__dirname, 'dist')
}
}
自定义配置文件名
$ npx webpack –config webpack.config.development.js
可在package.json中配置可执行的脚本命令(区分开发环境)
"scripts": {
"serve": "webpack --config webpack.config.development.js",
"build": "webpack --config webpack.config.production.js"
},
html-webpack-plugin
https://www.webpackjs.com/plugins/html-webpack-plugin/
$ npm i html-webpack-plugin –save-dev`
let HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
...,
//=>在webpack中使用插件
plugins: [
new HtmlWebpackPlugin({
//=>指定自己的模板
template: './src/index.html',
//=>输出的文件名
filename: 'index.html',
//=>给引入的文件设置HASH戳(清除缓存的),也可以在output中设置 filename: 'bundle.[hash].js' 来生成不同的文件
hash: true,
//=>控制是否以及以何种方式最小化输出
//=>https://github.com/kangax/html-minifier
minify: {
collapseWhitespace: true,
removeComments: true,
removeAttributeQuotes: true,
removeEmptyAttributes: true
}
})
]
}
clean-webpack-plugin
每一次打包之前,清除之前打包的内容
$ npm install clean-webpack-plugin –sav-dev
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports={
plugins:[
new CleanWebpackPlugin()
]
};
webpack-dev-server
https://webpack.js.org/configuration/dev-server/
$ npm install webpack-dev-server –save-dev
/* webpack.config.js */
//=>配置DEV-SERVER **内存中编译打包**
devServer: {
//=>端口
port: 3000,
//=>开启GZIP压缩
compress:true,
//=>显示编译进度
progress: true,
//=>指定访问资源目录
contentBase: path.resolve(__dirname, "dist"),
//=>自动打开浏览器
open: true,
//=>开启热更新
hot:true,
//=>请求代理
proxy:{
"/":{
target:"http://localhost:8888",
secure: false, //若为true则表示是https,false是http
changeOrigin: true //把请求头当中的host值改成服务器地址
}
}
}
/* package.json */
"scripts": {
"serve": "webpack-dev-server",
"build": "webpack"
}
4.多入口、多出口
const htmlPlugins = ['index', 'login'].map(chunk => {
return new HtmlWebpackPlugin({
template: `./${chunk}.html`,
filename: `${chunk}.html`,
hash: true,
chunks:[chunk,'jquery'],
minify: {
collapseWhitespace: true,
removeComments: true,
removeAttributeQuotes: true,
removeEmptyAttributes: true
}
});
});
module.exports={
entry: {
index: "./src/index.js",
login: "./src/login.js",
jquery:"./src/jquery.js"
},
output: {
filename: "[name].[hash].js",
path: path.resolve(__dirname, "dist")
},
plugins:[
...htmlPlugins
]
};
5.webpack中的加载器loader:处理样式的
$ npm install css-loader style-loader less less-loader autoprefixer postcss-loader –save-dev
module.exports = {
//=>配置模块加载器LOADER
module: {
//=>模块规则:使用加载器(默认从右向左执行,从下向上)
rules: [{
test: /\.(css|less)$/, //=>基于正则匹配哪些模块需要处理
use: [
"style-loader", //=>把CSS插入到HEAD中
"css-loader", //=>编译解析@import/URL()这种语法
"postcss-loader", //=>设置前缀
{
loader: "less-loader",
options: {
//=>加载器额外的配置
}
}
]
}]
}
}
postcss.config.js
module.exports = {
plugins: [
require('autoprefixer')
]
};
package.json
// https://github.com/browserslist/browserslist
"browserslist": [
"> 1%",
"last 2 versions"
]
6.mini-css-extract-plugin 抽离CSS内容
https://www.npmjs.com/package/mini-css-extract-plugin
$ npm install mini-css-extract-plugin –save-dev
const MiniCssExtractPlugin=require('mini-css-extract-plugin');
module.exports = {
plugins: [
//=>使用插件
new MiniCssExtractPlugin({
//=>设置编译后的文件名字
filename: 'main.[hash].css'
})
],
module: {
rules: [{
test: /\.(css|less)$/,
use: [
// "style-loader",
//=>使用插件中的LOADER代替STYLE方式
MiniCssExtractPlugin.loader,
"css-loader",
"postcss-loader",
"less-loader"
]
}]
}
}
7.设置优化项压缩CSS/JS
$ npm install optimize-css-assets-webpack-plugin uglifyjs-webpack-plugin terser-webpack-plugin –save-dev
const UglifyjsWebpackPlugin=require('uglifyjs-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCssAssetsWebpackPlugin= require('optimize-css-assets-webpack-plugin');
module.exports = {
//=>设置优化项
optimization: {
//=>设置压缩方式
minimizer: [
//=>压缩CSS(但是必须指定JS的压缩方式)
new OptimizeCssAssetsWebpackPlugin(),
//=>压缩JS
//new UglifyjsWebpackPlugin({
//cache: true, //=>是否使用缓存
//parallel: true, //=>是否是并发编译
//sourceMap: true, //=>启动源码映射(方便调试)
//}),
new TerserPlugin()
]
}
};
8.webpack中图片的处理
$ npm install file-loader url-loader html-withimg-loader –save-dev
module.exports = {
module: {
//=>模块规则:使用加载器(默认从右向左执行)
rules: [{
test: /\.(png|jpe?g|gif)$/i,
use: [{
//=>把指定大小内的图片BASE64
//=>不在指定范围的采用file-loader进行处理
loader: 'url-loader',
options: {
limit: 200 * 1024,
outputPath:'/images',
//name:'[name].[ext]'
}
}],
include: path.resolve(__dirname, 'src'),
exclude: /node_modules/
}, {
test:/\.(svg|eot|ttf|woff|woff2)$/i,
use:"file-loader"
}, {
test: /\.html$/,
use: ['html-withimg-loader']
}]
}
}
9.基于babel实现ES6的转换和ESLint语法检测
https://babeljs.io/
https://eslint.org/
$ npm install babel-loader @babel/core @babel/preset-env @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators @babel/plugin-transform-runtime –save-dev
$ npm insall @babel/runtime @babel/polyfill
$ npm install eslint eslint-loader –save-dev
module.exports = {
module: {
rules: [{
test: /\.js$/,
use: [{
loader: 'babel-loader',
options: {
//=>转换的语法预设(ES6->ES5)
presets: [
"@babel/preset-env"
],
//=>基于插件处理ES6/ES7中CLASS的特殊语法
plugins: [
["@babel/plugin-proposal-decorators", {
"legacy": true
}],
["@babel/plugin-proposal-class-properties", {
"loose": true
}],
"@babel/plugin-transform-runtime"
]
}
}], //=>, "eslint-loader"
//=>设置编译时忽略的文件和指定编译目录
include: path.resolve(__dirname, 'src'),
exclude: /node_modules/
}]
}
}
类的装饰器
@log
class A{
a=1;
}
function log(target){}