从零开始的Webpack4教程

1、了解Webpack相关

  • 什么是webpack

    • Webpack是一个模块打包器(bundler)。
    • 在Webpack看来, 前端的所有资源文件(js/json/css/img/less/...)都会作为模块处理
    • 它将根据模块的依赖关系进行静态分析,生成对应的静态资源
  • 五个核心概念

    • Entry:入口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。
    • Output:output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist。
    • Loader:loader 让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只能解析 JavaScript)。
    • Plugins:插件则可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量等。
    • Mode:模式,有生产模式production和开发模式development
  • 理解Loader

    • Webpack 本身只能加载JS/JSON模块,如果要加载其他类型的文件(模块),就需要使用对应的loader 进行转换/加载
    • Loader 本身也是运行在 node.js 环境中的 JavaScript 模块
    • 它本身是一个函数,接受源文件作为参数,返回转换的结果
    • loader 一般以 xxx-loader 的方式命名,xxx 代表了这个 loader 要做的转换功能,比如 json-loader。
  • 理解Plugins

    • 插件可以完成一些loader不能完成的功能。
    • 插件的使用一般是在 webpack 的配置信息 plugins 选项中指定。
  • 配置文件(默认)

    • webpack.config.js : 是一个node模块,返回一个 json 格式的配置信息对象

2、开启项目

  • 初始化项目:

    • 生成package.json文件

      {
        "name": "webpack_test",
        "version": "1.0.0"
      } 
  • 安装webpack

    • npm install webpack webpack-cli -g //全局安装
    • npm install webpack webpack-cli -D //本地安装

3、编译打包应用

  • 创建js文件

    • src/js/app.js
    • src/js/module1.js
    • src/js/module2.js
    • src/js/module3.js
  • 创建json文件

    • src/json/data.json
  • 创建主页面:

    • src/index.html
  • 运行指令

    • 开发配置指令:webpack src/js/app.js -o dist/js/app.js --mode=development

      • 功能: webpack能够编译打包js和json文件,并且能将es6的模块化语法转换成浏览器能识别的语法
    • 生产配置指令:webpack src/js/app.js -o dist/js/app.js --mode=production

      • 功能: 在开发配置功能上加上一个压缩代码
  • 结论:

    • webpack能够编译打包js和json文件
    • 能将es6的模块化语法转换成浏览器能识别的语法
    • 能压缩代码
  • 缺点:

    • 不能编译打包css、img等文件
    • 不能将js的es6基本语法转化为es5以下语法
  • 改善:使用webpack配置文件解决,自定义功能

4、使用webpack配置文件

  • 目的:在项目根目录定义配置文件,通过自定义配置文件,还原以上功能
  • 文件名称:webpack.config.js
  • 文件内容:

    const {resolve} = require('path'); //node内置核心模块,用来设置路径。
    module.exports = {
      entry: './src/js/app.js',   // 入口文件
      output: {                     // 输出配置
        filename: './js/bundle.js',      // 输出文件名
        path: resolve(__dirname, 'dist')   //输出文件路径配置
      },
      mode: 'development'   //开发环境(二选一)
      mode: 'production'   //生产环境(二选一)
    };
  • 运行指令: webpack

5、js语法检查

  • 安装loader

    • npm install eslint-loader eslint --save-dev
  • 配置loader

    module: {
      rules: [
        {
          test: /\.js$/,  //只检测js文件
          exclude: /node_modules/,  //排除node_modules文件夹
          enforce: "pre",  //提前加载使用
          use: { //使用eslint-loader解析
            loader: "eslint-loader" 
          }
        }        
      ]
    }
  • 修改package.json(需要删除注释才能生效)

    "eslintConfig": {   //eslint配置
      "parserOptions": {  
        "ecmaVersion": 8,  // es8
        "sourceType": "module", //  ECMAScript 模块
      }
    }
  • 运行指令:webpack

6、js语法转换

  • 安装loader

    • npm install babel-loader @babel/core @babel/preset-env --save-dev
  • 配置loader

    module: {
      rules: [
        {
          oneOf: [  //数组中的配置只有一个能够生效, 后面的配置都会放在当前数组中
            {
              test: /\.js$/,
              exclude: /node_modules/,
              use: {
                loader: "babel-loader",
                options: {
                  presets: ['@babel/preset-env']
                }
              }
            }
          ]
        }
      ]
    }
  • 运行指令:webpack

7、打包less资源

  • 创建less文件

    • src/less/test1.less
    • src/less/test2.less
  • 入口app.js文件

    • 引入less资源
  • 安装loader

    • npm install css-loader style-loader less-loader less --save-dev
  • 配置loader

    oneOf: [
      {
        test: /\.less$/,
        use: [{
          loader: "style-loader"
        }, {
          loader: "css-loader" 
        }, {
          loader: "less-loader" 
        }]
      }
    ]
  • 运行指令:webpack
  • 在index.html中引入打包生成的dist/js/bundle.js文件,观察效果

8、打包样式文件中的图片资源

  • 添加2张图片:

    • 小图, 小于8kb: src/images/1.png
    • 大图, 大于8kb: src/images/2.jpg
  • 在less文件中通过背景图的方式引入图片
  • 安装loader

    • npm install file-loader url-loader --save-dev
    • 补充:url-loader是对象file-loader的上层封装,使用时需配合file-loader使用。
  • 配置loader

    {
      test: /\.(png|jpg|gif|svg)$/,
      use: [
        {
          loader: 'url-loader',
          options: {
            outputPath: 'images/',   //在output基础上,修改输出图片文件的位置
            publicPath: '../dist/images/',  //修改背景图引入url的路径
            limit: 8 * 1024,  // 8kb大小以下的图片文件都用base64处理
            name: '[hash:8].[ext]'  // hash值为7位,ext自动补全文件扩展名
          }
        }
      ]
    }
  • 运行指令:webpack
  • 在index.html中引入打包生成的dist/js/bundle.js文件,观察效果

9、打包html文件

  • 添加html文件

    • src/index.html
    • 注意不要在html中引入任何css和js文件
  • 安装插件Plugins

    • npm install clean-webpack-plugin --save-dev
  • 在webpack.config.js中引入插件(插件都需要手动引入,而loader会自动加载)

    • const CleanWebpackPlugin = require('clean-webpack-plugin')
  • 配置插件Plugins

    plugins: [
      new HtmlWebpackPlugin({
        template: './src/index.html'
      }),
    ]
  • 运行指令:webpack

10、打包html中图片资源

  • 添加图片

    • 在src/index.html添加两个img标签
  • 安装loader

    • npm install html-loader --save-dev
  • 修改entry

    • entry: ['./src/js/app.js', './src/index.html']
  • 配置loader

    {
      test: /\.(html)$/,
      use: {
        loader: 'html-loader'
      }
    }
  • 运行指令:webpack

11、打包其他资源

  • 添加字体文件

    • src/media/iconfont.eot
    • src/media/iconfont.svg
    • src/media/iconfont.ttf
    • src/media/iconfont.woff
    • src/media/iconfont.woff2
  • 修改样式

    @font-face {
      font-family: 'iconfont';
      src: url('../media/iconfont.eot');
      src: url('../media/iconfont.eot?#iefix') format('embedded-opentype'),
      url('../media/iconfont.woff2') format('woff2'),
      url('../media/iconfont.woff') format('woff'),
      url('../media/iconfont.ttf') format('truetype'),
      url('../media/iconfont.svg#iconfont') format('svg');
    }
    
    .iconfont {
      font-family: "iconfont" !important;
      font-size: 16px;
      font-style: normal;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
    }
  • 修改html,添加字体
  • 配置loader

    {
      loader: 'file-loader',
      exclude: [/\.js$/, /\.html$/, /\.json$/],
      options: {
        outputPath: 'media/',
        publicPath: '../dist/media/',
        name: '[hash:8].[ext]',
      },
    }
  • 运行指令:webpack

12、自动编译打包运行

  • 安装loader

    • npm install webpack-dev-server --save-dev
  • 引入webpack

    • const webpack = require('webpack');
  • 修改webpack配置对象(注意不是loader中)

    devtool: 'inline-source-map',  // 将编译后的代码映射回原始源代码,更容易地追踪错误和警告
    devServer: {
      contentBase: './dist',  //项目根路径
      hot: true,  //开启热模替换功能
      open: true  //自动打开浏览器
    },
    plugins: [
      new webpack.NamedModulesPlugin(),
      new webpack.HotModuleReplacementPlugin()
    ]
  • 修改loader部分配置

    • 因为构建工具以dist为根目录,不用再找dist了
    • publicPath: '../dist/images/' --> publicPath: 'images/'
    • publicPath: '../dist/media/' --> publicPath: 'media/'
  • 修改package.json中scripts指令

    • "start": "webpack-dev-server",
    • "dev": "webpack-dev-server"
  • 运行指令:npm start / npm run dev
以上就是webpack开发环境的配置,可以在内存中自动打包所有类型文件并有自动编译运行、热更新等功能。

13、准备生产环境

  • 创建文件夹config,将webpack.config.js复制两份

    • webpack.dev.js
    • webpack.prod.js
  • 修改webpack.prod.js配置,删除webpack-dev-server配置

    module.exports = {
      output: {
        filename: 'js/[name].[hash:8].js',   //添加了hash值, 实现静态资源的长期缓存
        publicPath: '/'  //所有输出资源公共路径
      },
      module: {  //loader其他没有变化,只放了变化部分,只有需要修改路径部分改了
        rules: [
          {
            oneOf: [
              {
                test: /\.(png|jpg|gif|svg)$/,
                use: [
                  {
                    loader: 'url-loader',
                    options: {
                      limit: 8 * 1024,  // 8kb大小以下的图片文件都用base64处理
                      name: 'images/[name].[hash:8].[ext]'
                    }
                  }
                ]
              },
              {
                loader: 'file-loader',
                exclude: [/\.js$/, /\.html$/, /\.json$/],
                options: {
                  name: 'media/[name].[hash:8].[ext]',
                },
              }
            ]
          }
        ]
      },
      mode: 'production',  //修改为生产环境
    }
  • 修改package.json的指令

    • "start": "webpack-dev-server --config ./config/webpack.dev.js"
    • "dev": "webpack-dev-server --config ./config/webpack.dev.js"
    • "build": "webpack --config ./config/webpack.prod.js"
  • 开发环境指令

    • npm start
    • npm run dev
  • 生产环境指令

    • npm run build
    • 注意: 生产环境代码需要部署到服务器上才能运行

      • npm i serve -g
      • serve -s dist

14、清除打包文件目录

  • 安装插件

    • npm install clean-webpack-plugin --save-dev
  • 引入插件

    • const CleanWebpackPlugin = require('clean-webpack-plugin');
  • 配置插件

    new CleanWebpackPlugin()
  • 运行指令:npm run build

15、提取css成单独文件

  • 安装插件

    • npm install mini-css-extract-plugin --save-dev
  • 引入插件

    • const MiniCssExtractPlugin = require("mini-css-extract-plugin");
  • 配置loader

    {
      test: /\.less$/,
      use: [
        MiniCssExtractPlugin.loader,
        'css-loader',
        'less-loader',
      ]
    }
  • 配置插件

    new MiniCssExtractPlugin({
      filename: "css/[name].[hash:8].css",
      chunkFilename: "css/[id].[hash:8].css"
    })
  • 运行指令

    • npm run build
    • serve -s dist

16、添加css兼容

  • 安装loader

    • npm install postcss-loader autoprefixer --save-dev
  • 配置loader

    {
      test: /\.less$/,
      use: [
        MiniCssExtractPlugin.loader,
        'css-loader',
        'postcss-loader',
        'less-loader',
      ]
    }
  • 在项目根目录添加postcss配置文件:postcss.config.js

    module.exports = {
      "plugins": {
        "autoprefixer": {
          "browsers": [
            "ie >= 8",
            "ff >= 30",
            "chrome >= 34",
            "safari >= 8",
            "opera >= 23"
          ]
        }
      }
    }
  • 运行指令:

    • npm run build
    • serve -s dist

17、压缩css

  • 安装插件

    • npm install optimize-css-assets-webpack-plugin --save-dev
  • 引入插件

    • const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
  • 配置插件

    new OptimizeCssAssetsPlugin({
      cssProcessorPluginOptions: {
        preset: ['default', { discardComments: { removeAll: true } }],
      },
    })
  • 运行指令:

    • npm run build
    • serve -s dist

18、图片压缩

  • 安装loader

    • npm install img-loader imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo imagemin --save-dev
  • 配置loader

    {
      test: /\.(png|jpg|gif|svg)$/,
      use: [
        {
          loader: 'url-loader',
          options: {
            limit: 8 * 1024,  // 8kb大小以下的图片文件都用base64处理
            name: 'images/[name].[hash:8].[ext]'
          }
        },
        {
          loader: 'img-loader',
          options: {
            plugins: [
              require('imagemin-gifsicle')({
                interlaced: false
              }),
              require('imagemin-mozjpeg')({
                progressive: true,
                arithmetic: false
              }),
              require('imagemin-pngquant')({
                floyd: 0.5,
                speed: 2
              }),
              require('imagemin-svgo')({
                plugins: [
                  { removeTitle: true },
                  { convertPathData: false }
                ]
              })
            ]
          }
        }
      ]
    }
  • 运行指令:

    • npm run build
    • serve -s dist

19、压缩html

  • 修改插件配置

    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeRedundantAttributes: true,
        useShortDoctype: true,
        removeEmptyAttributes: true,
        removeStyleLinkTypeAttributes: true,
        keepClosingSlash: true,
        minifyJS: true,
        minifyCSS: true,
        minifyURLs: true,
      }
    })
  • 运行指令:

    • npm run build
    • serve -s dist
以上就是webpack生产环境的配置,可以生成打包后的文件。

到这里基本配置已经告一段落了,所有配置我已经放在 仓库

第二期 Webpack4优化教程 已出~ 欢迎关注和提问~

非知名人士

464 声望
32 粉丝
0 条评论
推荐阅读
你还没有听过React不完全手册?😱😱
完全是不可能滴, 这辈子都不可能完全!        -- 来自某非著名码农 本文总结 React 实用的特性,部分实验性和不实用的功能将不会纳入进来,或许未来可期~ 1、setState 面试题 {代码...} 总结 setState 只在 React...

xpromise25阅读 1.5k

从零搭建 Node.js 企业级 Web 服务器(零):静态服务
过去 5 年,我前后在菜鸟网络和蚂蚁金服做开发工作,一方面支撑业务团队开发各类业务系统,另一方面在自己的技术团队做基础技术建设。期间借着 Node.js 的锋芒做了不少 Web 系统,有的至今生气蓬勃、有的早已夭折...

乌柏木142阅读 11.9k评论 10

从零搭建 Node.js 企业级 Web 服务器(十五):总结与展望
总结截止到本章 “从零搭建 Node.js 企业级 Web 服务器” 主题共计 16 章内容就更新完毕了,回顾第零章曾写道:搭建一个 Node.js 企业级 Web 服务器并非难事,只是必须做好几个关键事项这几件必须做好的关键事项就...

乌柏木60阅读 6k评论 16

再也不学AJAX了!(二)使用AJAX ① XMLHttpRequest
「再也不学 AJAX 了」是一个以 AJAX 为主题的系列文章,希望读者通过阅读本系列文章,能够对 AJAX 技术有更加深入的认识和理解,从此能够再也不用专门学习 AJAX。本篇文章为该系列的第二篇,最近更新于 2023 年 1...

libinfs39阅读 6.2k评论 12

封面图
从零搭建 Node.js 企业级 Web 服务器(一):接口与分层
分层规范从本章起,正式进入企业级 Web 服务器核心内容。通常,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,如下图:从上至下,抽象层次逐渐加深。从下至上,业务细节逐渐清晰。视图...

乌柏木39阅读 7.1k评论 6

【关于Javascript】--- 正则表达式篇
基础知识一、元字符 {代码...} 二、量词 {代码...} 三、集合 字符类 {代码...} 四、分支 {代码...} 五、边界 开始结束 {代码...} 六、修饰符 {代码...} 七、贪婪模式和非贪婪模式js默认贪婪模式即最大可能的匹配...

Jerry35阅读 2.9k

从零搭建 Node.js 企业级 Web 服务器(二):校验
校验就是对输入条件的约束,避免无效的输入引起异常。Web 系统的用户输入主要为编辑与提交各类表单,一方面校验要做在编辑表单字段与提交的时候,另一方面接收表单的接口也要做足校验行为,通过前后端共同控制输...

乌柏木32阅读 6.1k评论 9

非知名人士

464 声望
32 粉丝
宣传栏