写点什么

2022-webpack5 实战教程

作者:Geek_02d948
  • 2022-10-25
    浙江
  • 本文字数:6342 字

    阅读完需:约 21 分钟

前言

手摸手教你如何打包,让你在动手的实践过程中感受 webpack。


在动手之前,你可先简单了解一下 webpack 的概念


每一小结都有对应的分支,方便大家学习


webpack 版本:5.58.1

入门

新建一个目录,初始化 npm


npm init


接下来安装webpackwebpack-cli两个包


npm i -D webpack webpack-cli

默认配置

新建一个文件夹src ,里面新建一个main.js,写一点测试代码


console.log("webpack")


在 package.json 中 scripts 中添加新的命令


"scripts": {  "build": "webpack ./src/main.js"},
复制代码


执行打包命令npm run build


此时如果生成了一个 dist 文件夹,并且内部含有 main.js 说明已经打包成功了


这个例子只是 webpack 自己默认的配置,下面我们要实现更加丰富的自定义配置

自定义配置

新建一个build文件夹,里面新建一个webpack.config.js


const path = require('path');
module.exports = { mode:'development', // 开发模式 entry: path.resolve(__dirname,'../src/main.js'), // 入口文件 output: { filename: 'output.js', // 打包后的文件名称 path: path.resolve(__dirname,'../dist') // 打包后的目录 }}
复制代码


更改打包命令


{  // ...  "scripts": {    "build": "webpack --config build/webpack.config.js"  },}
复制代码


然后执行 npm run build,会得到如下结果



其中 main.js 是我们第一次打包遗留的。


js 已经打包好了,接下来我们要做的就是将 js 引入到 html 文件中

添加 js 到 html 文件

我们需要 html-webpack-plugin 来帮我们完成这件事情


npm i -D html-webpack-plugin


新建一个与build同级的文件夹public,里面新建一个index.html


配置如下


const path = require('path');const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = { mode:'development', // 开发模式 entry: path.resolve(__dirname,'../src/main.js'), // 入口文件 output: { filename: '[name].[hash:8].js', // [name] 指entry属性名字, 默认为main path: path.resolve(__dirname,'../dist') // 打包后的目录 }, plugins:[ new HtmlWebpackPlugin({ // 选取一个html作为模版,在dist目录下会生成一个相同的html,之后将打包好的js注入到该html文件 template: path.resolve(__dirname,'../public/index.html') }) ]}
复制代码


打包成功之后,查看 dist 目录下的 index.html 文件是否引用了打包之后的 js

多文件如何注入到 html

  1. 多个入口文件,注入到同一个 html 文件中


这种情形我们只需添加入口就 OK 了,html-webpack-plugin插件会自动把所有打包好的 js 注入到 html 里


module.exports = {  // ...  entry: {    main: path.resolve(__dirname,'../src/main.js'),    share: path.resolve(__dirname,'../src/share.js')  }}
复制代码


  1. 多个入口文件,根据不同需求注入到不同的 html 文件


我们可以通过生成多个 html-webpack-plugin 实例来解决这个问题


module.exports = { // ...  plugins:[    new HtmlWebpackPlugin({      // 选取一个html作为模版,在dist目录下会生成一个相同的html,之后将打包好的js注入到该html文件      template: path.resolve(__dirname,'../public/index.html'),      filename: 'index.html',      chunks: ['main'] // 配置将哪些文件注入到该html文件,为[]在代表不注入js,若无该属性,默认注入所有js    }),    new HtmlWebpackPlugin({      template: path.resolve(__dirname,'../public/share.html'),      filename: 'share.html',      chunks: ['share']    })  ] }
复制代码

打包前清空 dist 目录

相信大家也发现了,dist 目录下的文件越来越多,下面我们就来解决这个问题


我们需要 clean-webpack-plugin 来帮我们完成这件事情


npm i -D clean-webpack-plugin


// 其余配置同上const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = { plugins:[ // ... new CleanWebpackPlugin() ] }
复制代码


经掘友提醒,webpack5 有新增清空 dist 目录的方式,在 output 增加 clean 字段,现补充在下面


module.exports = {  // ...  output: {      filename: '[name].[hash:8].js', // [name] 指entry属性名字, 默认为main      path: path.resolve(__dirname,'../dist'), // 打包后的目录      clean: true  },}
复制代码

将 css 以 style 标签的方式注入到 html

我们的入口文件是 js,所以我们在入口 js 中引入我们的 css 文件


// main.jsimport "../static/css/base.css"import "../static/css/color.scss"import "../static/css/fontsize.less"
console.log("webpack")
复制代码


我们需要一些 loader 来解析我们的 css 文件


npm i -D style-loader css-loader


如果使用 less 来构建样式,则需要安装


npm i -D less less-loader


如果使用 scss 来构建样式,则需要安装


npm i -D node-sass sass-loader


配置文件如下


module.exports = {  // ...  module: {    rules: [      {        test: /\.css$/,        use: ["style-loader", "css-loader"] // 从右向左开始解析      },      {        test: /\.scss$/,        use: ["style-loader", "css-loader", "sass-loader"] // 此外还需要安装node-sass(sass也行)      },      {        test:/\.less$/,        use:['style-loader','css-loader','less-loader'] // 此外还需要安装less模块      }    ]  }}
复制代码


打包之后在浏览器中打开 html 文件,就能看见我们注入的 css


为 css 添加浏览器前缀

为了适配更多的浏览器样式我们需要给 css 加上前缀


我们需要 postcss-loader 以及autoprefixer来帮我们完成这件事情


参考 webpack 视频讲解:进入学习


引入autoprefixer方式有两种


  1. postcss.config.js引入(推荐)


**项目根目**录下创建postcss.config.js,配置如下


module.exports = {  plugins: [    require('autoprefixer')  ]}
复制代码


然后直接在webpack.config.js中引入


module.exports = {  // ...  module: {    rules: [      {        test: /\.css$/,        use: ["style-loader", "css-loader", "postcss-loader"] // 从右向左开始解析      },      {        test: /\.scss$/,        use: ["style-loader", "css-loader", "postcss-loader", "sass-loader"] // 此外还需要安装node-sass(sass也行)      },      {        test:/\.less$/,        use:['style-loader','css-loader', "postcss-loader", 'less-loader'] // 此外还需要安装less模块      }    ]  } }
复制代码


  1. 直接在webpack.config.js配置


moudule.exports = { // ...  module: {    rules: [      {        test: /\.css$/,        use: ["style-loader", "css-loader", {          loader: "postcss-loader",          options: {            postcssOptions: {              plugins: [                ['autoprefixer']              ]            }          }        }] // 从右向左开始解析      },      {        test: /\.scss$/,        use: ["style-loader", "css-loader", {          loader: "postcss-loader",          options: {            postcssOptions: {              plugins: [                ['autoprefixer']              ]            }          }        }, "sass-loader"] // 此外还需要安装node-sass(sass也行)      },      {        test:/\.less$/,        use:['style-loader','css-loader', {          loader: "postcss-loader",          options: {            postcssOptions: {              plugins: [                ['autoprefixer']              ]            }          }        }, 'less-loader'] // 此外还需要安装less模块      }    ]  } }
复制代码


完成上述配置之后,我们发现 css 并未成功加上前缀。这里我们还要进行一步操作,那就是配置package.json,在package.json中添加如下配置


{ // ..."browserslist": [    "defaults",    "not ie < 11",    "last 2 versions",    "> 1%",    "iOS 7",    "last 3 iOS versions"  ]}
复制代码

外链引入 css 文件

上述我们通过 style 标签的方式加载我们的样式,但如果 css 文件过多就显得很混乱。


我们需要 mini-css-extract-plugin 帮我们实现


npm i -D mini-css-extract-plugin


// 其余配置保持不变const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = { // ... plugins: [ // ... new MiniCssExtractPlugin({ filename: "[name].[hash].css", }) ], module: { rules: [ { test: /\.css$/, use: [MiniCssExtractPlugin.loader, "css-loader", "postcss-loader"] // 从右向左开始解析 }, { test: /\.scss$/, use: [MiniCssExtractPlugin.loader, "css-loader", { loader: "postcss-loader", options: { postcssOptions: { plugins: [ ['autoprefixer'] ] } } }, "sass-loader"] // 此外还需要安装node-sass(sass也行) }, { test:/\.less$/, use:[MiniCssExtractPlugin.loader,'css-loader', "postcss-loader", 'less-loader'] // 此外还需要安装less模块 } ] }}
复制代码


不过通过这种方式会将所有的 css 合并到一个 css 文件里,如果想要拆分就只有用其他办法里,网上看别人用的是extract-text-webpack-plugin,不过当我去 npm 官网看时。



所以这里就先不讨论拆分 css 了

图片处理

css 与 js 中图片处理只需添加如下配置就行


module.exports = {    // ...  module: {    rules: [        // ...      {        test: /\.(jpe?g|png|gif)$/i,        type: "asset",        generator: {          filename: 'static/[name].[hash].[ext]'        }      },    ]  }}
复制代码


如果需要处理 html 中的图片则需要用到 html-loader


npm i -D html-loader


配置如下


module.exports = {    // ...  module: {    rules: [        // ...      {        test: /\.html$/i,        loader: "html-loader"      },    ]  }}
复制代码


如果需要配置更多的资源文件,请参考资源模块

转义 js 文件

为了使我们的 js 代码兼容更多的环境我们需要转义我们的 js 文件


npm i -D babel-loader @babel/preset-env @babel/core core-js


module.expors = {  // ...  module: {    rules: [      // ...      {        test: /\.js$/,        use: {          loader: 'babel-loader',          options: {            presets: [              [                '@babel/preset-env',                {                  useBuiltIns: 'usage',                  corejs: {                    //core-js的版本                    version: 3                  },                  //需要兼容的浏览器                  targets: {                    chrome: '60',                    firefox: '60',                    ie: '9',                    safari: '10',                    edge: '17'                  }                }              ]            ],          }        },        exclude: /node_modules/      }    ]  }}
复制代码


babel-loader负责将 ES6/7/8 等语法转换为 ES5 语法


core-js负责将新的 api 进行转化,例如 promise、Generator、Set、Maps、Proxy 等

进阶

搭建 Vue 开发环境

Vue 文件处理

首先安装必要依赖


npm i -D vue-loader vue-template-compiler vue-style-loader


npm i -S vue


vue-loader 用于解析.vue文件


vue-template-compiler 用于编译模板


vue-style-loader 解析样式


const vueLoaderPlugin = require('vue-loader/lib/plugin')module.exports = {  // ...  module:{    rules:[      // 这一个loader必须放在最前面      {        test:/\.vue$/,        use:['vue-loader']      }      // ...    ]  },  resolve:{    // 设置路径别名    alias:{      'vue$':'vue/dist/vue.runtime.esm.js',      '@':path.resolve(__dirname,'../src')    },    // 尝试按顺序解析这些后缀名。    // 如果有多个文件有相同的名字,但后缀名不同,webpack 会解析列在数组首位的后缀的文件 并跳过其余的后缀。    extensions:['*','.js','.json','.vue']  },  plugins:[    new vueLoaderPlugin()  ]}
复制代码

热更新配置

我们需要使用 webpack-dev-server 来启动一个本地服务并且配置热更新


npm i -D webpack-dev-server


配置如下


const Webpack = require('webpack')module.exports = {  // ...  devServer:{    port:3000,    hot:true  },  plugins:[    new Webpack.HotModuleReplacementPlugin()  ]}
复制代码


配置打包命令


"scripts": {  // ...  "dev": "webpack-dev-server --config build/webpack.config.js --open"},
复制代码


添加 --open可自动打开 http://localhost:3000页面


接下来写几行代码进行测试,先修改我们的 main.js


// main.jsimport Vue from 'vue'import App from './App.vue'
new Vue({ render: h => h(App)}).$mount('#app')
复制代码


新建一个 App.vue 文件


<template>  <div>    {{msg}}  </div></template>
<script>export default { data() { return { msg: "webpack vue" } }}</script>
<style lang='scss' scoped>div { color: aquamarine; display: flex;}</style>
复制代码


修改原来的 index.html


<!DOCTYPE html><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>webpack</title></head><body>  <div id="app"></div></body></html>
复制代码


最后执行npm run dev

区分开发环境和生产环境

development(开发环境) 和 **production(生产环境) **这两个环境下的构建目标存在着巨大差异。在开发环境中,我们需要:强大的 source map 和一个有着 live reloading(实时重新加载) 或 hot module replacement(热模块替换) 能力的 localhost server。而生产环境目标则转移至其他方面,关注点在于压缩 bundle、更轻量的 source map、资源优化等,通过这些优化方式改善加载时间。由于要遵循逻辑分离,我们通常建议为每个环境编写彼此独立的 webpack 配置。


我们在原来webpack.config.js的基础上再新增两个文件webpack.prod.jswebpack.dev.js


这里我们需要使用 webpack-merge 帮我们 merge 代码


npm i -D webpack-merge



// webpack.dev.jsconst { merge } = require('webpack-merge');const common = require('./webpack.config.js')
module.exports = merge(common, { mode: 'development', devtool: 'inline-source-map', devServer:{ port:3000, hot:true }});
复制代码


// webpack.prod.jsconst { merge } = require('webpack-merge');const common = require('./webpack.config.js');
module.exports = merge(common, { mode: 'production',});
复制代码


原先的webpack.config.js也需要做出修改,我们只需要删除modedevserver字段就行了


最后修改package.json中的scripts命令


"scripts": {    "build": "webpack --config build/webpack.prod.js",    "dev": "webpack-dev-server --config build/webpack.dev.js --open"  },
复制代码


开发环境运行npm run dev,打包npm run build

最后

码字不易,若是对你有帮助,那就点个赞吧


用户头像

Geek_02d948

关注

还未添加个人签名 2022-09-08 加入

还未添加个人简介

评论

发布
暂无评论
2022-webpack5实战教程_webpack_Geek_02d948_InfoQ写作社区