webpack工程化实战
Posted 前端小嘟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了webpack工程化实战相关的知识,希望对你有一定的参考价值。
随着前端技术发展,掌握前端工程化越发成为前端工程师必要的条件。日常开发者中,我们常在用例如vue-cli 、 create-react-app等脚手架构建我们项目。但是如果你想在团队脱颖而出,那就需要花费一部分时间去学习webpack
本文各插件版本将在文章末尾为大家呈现
新建目录,初始化npm
npm init
1.1安装webpack包(建议将三个包同时安装)
npm i -D webpack webpack-cli webpack-dev-server
npm i -D 为npm install --save-dev的缩写
npm i -S 为npm install --save的缩写
新建webpack.config.js,实现更多的自定义配置
//webpack.config.js
const path = require('path')
module.export = {
entry:path.resolve(__dirname,'./src/index.js') //入口文件
output:{
filename:'bundle.js', //打包后的文件名称
path:path.resolve(__dirname,'./build') //打包后的目录
}
}
配置完webpack.config.js之后可以尝试着新建文件打包一下
html-webpack-plugin
//使用html-webpack-plugin创建html页面,并将打包后的js文件需要引入到html中 使用该插件引入对应的js文件
npm i -D html-webpack-plugin
//新建build同级的文件夹public 新建一个index.html
clean-webpack-plugin
npm i -D clean-webpack-plugin
将dist文件夹残留上次打包的文件清空
在引入css时也需要一些loader来解析我们的css
npm i -D style-loader css-loader
css-loader 的作用是将 CSS 模块转换为一个 JS 模块,但不会使用这个模块
style-loader 就可以把css-loader转化的模块通过style标签追加到页面上
//是将 css 装载到 javascript;style-loader 是让 javascript 认识css,require 时用
使用less构建样式
npm i -D less less-loader //less-loader 是将less转化为css
配置文件如下
// webpack.config.js
module.exports = {
// ...省略其他配置
module:{
rules:[
{
test:/\.css$/,
use:['style-loader','css-loader'] // 切记从右向左解析原则
},
{
test:/\.less$/,
use:['style-loader','css-loader','less-loader'] // 从右向左解析原则
}
]
}
}
npm i -D postcss-loader autoprefixer
//为了兼容各浏览器 添加此插件
需要在根目录创建postcss.config.js 文件
module.exports = {
plugins: [require('autoprefixer')] // 引用该插件
}
npm i -D mini-css-extract-plugin
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
//...省略其他配置
module: {
rules: [
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader'
],
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].[hash].css",
chunkFilename: "[id].css",
})
]
}
需要配置 MiniCssExtractPlugin 插件 一起使用
需要注意版本对应的关系
ES6/7/8
转 ES5
代码
npm i -D babel-loader @babel/preset-env @babel/core @babel/plugin-proposal-decorators
npm i -D @babel/plugin-transform-arrow-functions @babel/plugin-transform-runtime
在webpack5中 svg属于inline asset,内置loader
图片字体等文件在webpack5中内置了loader,按照如下配置即可无需引入依赖,路径自己定义即可。
//以上配置省略
module:{
rules:[
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
// 用正则去匹配要用该 loader 转换的 CSS 文件
test: /\.css$/,
exclude: path.resolve(__dirname, 'node_modules'),
use: [ 'style-loader', 'css-loader','postcss-loader']
},
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
// 缓存,加快babel-loader编译速度
cacheDirectory: true,
// 一系列插件的集合,包括处理箭头函数等,配置后是否需要配置plugins? 后面再看
// 2021/5/12 结论:不需要配置其他plugins
// useBuiltIns corejs 解决es6新增api无法编译问题(只能编译语法,例如箭头函数)
presets: [
// ['@babel/preset-env', { targets: 'defaults' }]
['@babel/preset-env', { useBuiltIns: 'usage', corejs: 3, targets: 'defaults' }]
],
plugins: [
// 编译箭头函数
'@babel/plugin-transform-arrow-functions',
// 编译装饰器
['@babel/plugin-proposal-decorators', { legacy: true }],
// 编译类,loose true时是赋值法定义属性,false时是使用Object.defineProperty定义属性,后者是默认
['@babel/plugin-proposal-class-properties', { loose: false }]
]
}
}
},
{
test:/\.svg$/,
type:'asset/inline',
generator:{
filename:"icons/[name]--[hash].[ext]"
}
},
{
test:/\.(png|jpe?g|gif)(\?.*)?$/,
type:'asset/resource',
generator: {
filename: 'imgs/[name]--[hash].[ext]'
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
type: 'asset/resource',
generator: {
filename: 'media/[name]--[hash].[ext]'
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
type: 'asset/resource',
generator: {
filename: 'fonts/[name]--[hash].[ext]'
}
}
]
},
结合上面例子的依赖,还需要以下几种配置
npm i -D vue-loader vue-template-compiler vue-style-loader
npm i -S vue
vue-loader
用于解析.vue
文件
vue-template-compiler
用于编译模板
具体配置见后文完整配置
devServer: {
contentBase: path.join(__dirname, './dist'),
compress: true,
port: 3000,
hot: true,
open: true
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --watch --config webpack.config.js",
"dev": "webpack serve"
},
在src下新建index.js
import Vue from 'vue'
import App from './App.vue'
new Vue({
render: h => h(App)
}).$mount('#app')
if (module.hot) {
module.hot.accept('./App.vue', function () {
})
module.hot.accept('./show.js', function () {
})
}
<template>
<div id="app">{{str}}</div>
</template>
<script>
console.log('app 加载了')
export default {
name: 'App',
data () {
return {
str: 'hello3'
}
},
mounted () {
console.log(Math.trunc(12.1))
},
methods: {
}
}
</script>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- <p id="app"></p>
<img id="testimg" alt="">
<div>bfg</div> -->
<div id="app"></div>
</body>
</html>
新建完各页面 执行npm run dev如果浏览器出现Vue开发环境成功,那么一个基础的基于vue的webpack打包工具就完成了
const path = require('path');
const htmlWebpackPlugin = require('html-webpack-plugin') //引入对应文件
const webpack = require('webpack')
const { VueLoaderPlugin } = require('vue-loader')
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
//将css样式从js文件中提取到单独css文件
// const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
// 默认路径,将entry的前置路径放到这个字段
// context:path.resolve(__dirname,'src'),
entry:path.resolve(__dirname,'./src/index.js'),
output:{
// 把所有依赖的模块合并输出到一个 bundle.js 文件
filename:'[name].[hash:8].js',
path:path.resolve(__dirname,'./build')
},
devServer: {
contentBase: path.join(__dirname, './dist'),
compress: true,
port: 3000,
hot: true,
open: true
},
devtool: 'source-map',
module:{
rules:[
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
// 用正则去匹配要用该 loader 转换的 CSS 文件
test: /\.css$/,
exclude: path.resolve(__dirname, 'node_modules'),
use: [ 'style-loader', 'css-loader','postcss-loader']
},
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
// 缓存,加快babel-loader编译速度
cacheDirectory: true,
// 一系列插件的集合,包括处理箭头函数等,配置后是否需要配置plugins? 后面再看
// 2021/5/12 结论:不需要配置其他plugins
// useBuiltIns corejs 解决es6新增api无法编译问题(只能编译语法,例如箭头函数)
presets: [
// ['@babel/preset-env', { targets: 'defaults' }]
['@babel/preset-env', { useBuiltIns: 'usage', corejs: 3, targets: 'defaults' }]
],
plugins: [
// 编译箭头函数
'@babel/plugin-transform-arrow-functions',
// 编译装饰器
['@babel/plugin-proposal-decorators', { legacy: true }],
// 编译类,loose true时是赋值法定义属性,false时是使用Object.defineProperty定义属性,后者是默认
['@babel/plugin-proposal-class-properties', { loose: false }]
]
}
}
},
{
test:/\.svg$/,
type:'asset/inline',
generator:{
filename:"icons/[name]--[hash].[ext]"
}
},
{
test:/\.(png|jpe?g|gif)(\?.*)?$/,
type:'asset/resource',
generator: {
filename: 'imgs/[name]--[hash].[ext]'
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
type: 'asset/resource',
generator: {
filename: 'media/[name]--[hash].[ext]'
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
type: 'asset/resource',
generator: {
filename: 'fonts/[name]--[hash].[ext]'
}
}
]
},
plugins:[
new htmlWebpackPlugin({
filename:'index.ejc',
template:path.resolve(__dirname,'./src/index.html')
}),
new CleanWebpackPlugin(),
new webpack.HotModuleReplacementPlugin(),
new VueLoaderPlugin()
]
}
实际运用到项目时, 需要区分开发环境与生产环境的关系
新建两个文件夹
webpack.dev.js
开发环境使用webpack.prod.js
生产环境使用webpack.config.js
公用配置
不需要压缩代码
需要热更新
css不需要提取到css文件
devtool使用source-map
...
压缩代码
不需要热更新
提取css,压缩css文件
sourceMap
构建前清除上一次构建的内容
...
npm i optimize-css-assets-webpack-plugin mini-css-extract-plugin clean-webpack-plugin webpack-merge copy-webpack-plugin -D
webpack-merge
合并配置copy-webpack-plugin
拷贝静态资源optimize-css-assets-webpack-plugin
压缩cssuglifyjs-webpack-plugin
压缩js
// 开发环境
// webpack中引入的path[require('path')]是node.js内置的package,用来处理路径的。
const webpackConfig = require('./webpack.config.js')
const WebpackMerge = require('webpack-merge')
const webpack = require('webpack')
// Webpack-merge 提供了一个函数,该函数将数组串联并合并创建新对象的对象。如果遇到函数,它将执行它们,通过算法运行结果,然后再次将返回的值包装在函数中。
module.exports = WebpackMerge.merge(webpackConfig,{
mode:'development',
devtool:'source-map',
devServer:{
port:3000,
hot:true,
contentBase:'./build'
},
plugins:[
new webpack.HotModuleReplacementPlugin()
]
})
const path = require('path')
const webpackConfig = require('./webpack.config.js')
const WebpackMerge = require('webpack-merge')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin') //压缩css
const UglifyJsPlugin = require('uglifyjs-webpack-plugin') //压缩js
module.exports = WebpackMerge.merge(webpackConfig,{
mode:'production',
devtool:'cheap-module-source-map',
plugins:[
new CopyWebpackPlugin({
patterns:[{
from:path.resolve(__dirname,'src'),
to:path.resolve(__dirname,'build')
}]}),
],
optimization:{
minimizer:[
new UglifyJsPlugin({//压缩js
cache:true,
parallel:true,
sourceMap:true
}),
new OptimizeCssAssetsPlugin({})
],
splitChunks:{
chunks:'all',
cacheGroups:{
libs: {
name: "chunk-libs",
test: /[\\/]node_modules[\\/]/,
priority: 10,
chunks: "initial" // 只打包初始时依赖的第三方
}
}
}
}
})
{
"name": "webpack-new",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --watch --config webpack.prod.js",
"dev": "webpack-dev-server --config webpack.dev.js"
},
"author": "",
"license": "ISC",
"keywords": [],
"description": "",
"devDependencies": {
"@babel/core": "^7.14.6",
"@babel/plugin-proposal-decorators": "^7.14.5",
"@babel/plugin-transform-arrow-functions": "^7.14.5",
"@babel/plugin-transform-runtime": "^7.14.5",
"@babel/preset-env": "^7.14.7",
"autoprefixer": "^10.2.6",
"babel-loader": "^8.2.2",
"clean-webpack-plugin": "^3.0.0",
"copy-webpack-plugin": "^9.0.1",
"css-loader": "^5.2.6",
"html-webpack-plugin": "^5.3.2",
"mini-css-extract-plugin": "^1.6.2",
"optimize-css-assets-webpack-plugin": "^6.0.1",
"postcss-loader": "^6.1.0",
"style-loader": "^2.0.0",
"uglifyjs-webpack-plugin": "^2.2.0",
"vue": "^2.6.14",
"vue-loader": "^15.9.7",
"vue-router": "^3.5.2",
"vue-template-compiler": "^2.6.14",
"vuex": "^3.6.2",
"webpack": "^5.40.0",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.2",
"webpack-merge": "^5.8.0"
}
}
交流讨论
到目前为止,我们已经成功的自己搭建了一个基础vue 开发环境,不过想要获取更好的offer、更高的薪水,还需要继续深入学习,在此来一波预告吧《webpack工程化实战(2)优化webpack配置》,看完文章,同学们可以搭建一下,搭建过程中会遇到许多的坑,同学可以在后台留言,或者微信私信我都可以,好了这一期就到这里了。
如果觉得这篇文章还不错,来个【分享、点赞、在看】三连吧,让更多的人也看到~
以上是关于webpack工程化实战的主要内容,如果未能解决你的问题,请参考以下文章