资讯专栏INFORMATION COLUMN

Webpack入门到精通(1)

SunZhaopeng / 864人阅读
前言

什么是webpack 本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。 webpack 有哪些功能(代码转换 文件优化 代码分割 模块合并 自动刷新 代码校验 自动发布) 首先学习webpack 需要有简单的node 基础 ,打开node 官方网站进行安装node, nodejs.cn/ 下载最新版node包并进行安装。

学习目标:

    webpack 常见配置 webpack高级配置

    webpack优化策略

    AST抽象语法树

    webpack中的Tapable

    掌握webpack流程 手写 webpack

    手写webpack中常见的loader

    手写webpack 中常见的plugin

定义好学习目标让我们开启webpack 的新旅程。(本文学习主要针对webpack4.0 进行学习讲解)


webpck--->基础搭建与使用:

安装完毕在终端 快速创建node项目 执行命令npm init -y 生成packge.json
在当前目录安装本地webpack 终端执行命令: npm i webpack webpack-cli -d i表示install ,d表示当前是开发环境安装完成会产生node_modules文件 webpack 可以进行0配置 并且webpack是打包工具(默认是js模块 通过入口进行打包输出打包后js结果)。
创建src目录 --> 创建index.js -> 输出:console.log("hello webpack");
npx 语法进行把index.js 进行打包
终端执行命令: npx webpack 我们发现当前目录生成了一个dist 目录并且创建了一个main.js(如图:)

执行顺序:(默认找node_modules--->bin文件 --> webpack文件 )
这里我们明白了安装webpack 必须安装他的依赖 webpack-cli webpack打包默认支持js模块化 ->类似于common.js

webpack:两种默两种模式如果没有创建webpack.config.js 配置文件指定mode (production/development)生成模式或开发模式,打包运行会直接默认生产模式打包并且进行压缩。
这里说一下webpack配置文件的默认名称有两种 (webpack.config.js / webpackfile.js 一般情况下我们会选择前一种)

如何手动配置webpack呢?其实比较简单

(1)创建webpack.config.js 配置文件 由于webpack是node.js的框架所以配置文件中要采用node语法来进行编辑。

const path = require("path"); //webpack内部方法path组件
module.exports = {
  mode: "development", //打包模式 development开发模式
  entry: "./src/index.js", //入口文件指定
  output: {
    //出口文件配置 配置出口打包路径
    filename: "build.js", //打包后的文件名称
    path: path.resolve(__dirname, "build") //resolve绝对路径引入
  }
};

我们分析一下build.js 打包出的结果,默认下是一个匿名函数 并且接收两个参数 接收一个对象,Key : value (key:是当前模块的路径 value:是一个执行函数)

接收到modules 里 先定义一个缓存对象 installedModules先定一个缓存目的是如果我当前模块加载完成没有必要再进行加载
webpack_require 实现了一个require方法因为浏览器无法直接执行node的require方法 (详解如图)

执行__webpack_require__ 发现接收了一个入口模块



终端运行: npx webpack , 发现我们打包当前目录产生了文件夹build目录
分析了一下打包文件是不是感觉webpack 源码没有想象的那么难 继续我们webpack 的探索之旅。
如何更改webpack 配置文件名称呢其实很简单重命名webpack.config.js (webpack.test.js)
执行命令: npx webpack --config webpack.test.js 发现可以执行webpack打包。
这样打包我发现命令很长所以我们利用packge.json 来配置打包脚本在scripts-->添加build.

"scripts": {
 "test": "echo "Error: no test specified" && exit 1",
 "build": "webpack --config webpack.config.js"
}
```
终端运行 npm run build  发现执行打包结果一样.   
(2)webpack 其他配 -->置插件的使用不会生成文件会生成内存中的打包  
安装webpck内置服务 webpack-dev-server 好处是 
终端执行命令: npm i webpack-dev-server -d -save
安装完成可以执行 npx webpack-dev-server 按提示打开http://localhost:8080/ 
如何配置开发服务运行目录可以在配置文件中添加在webpack.config.js添加devServer
````JavaScript
const path = require("path");
module.exports = {
mode: "development", //打包模式
entry: "./src/index.js", //入口文件指定
output: {
 //出口文件配置 配置出口打包路径
 filename: "build.js", //打包的文件名称
 path: path.resolve(__dirname, "build") //resolve绝对路径引入
},
devServer: {
 //开发服务器配置
 contentBase: "./build", //指向打包目录
 port: 3000, //服务端口号
 progress: true, //打包进度
 open: true, //是否打开浏览器
 compress: false //是否压缩
}
};

在packge.json中添加start 启动服务脚本

"scripts": {
    "test": "echo "Error: no test specified" && exit 1",
    "build": "webpack --config webpack.config.js",
    "start":"webpack-dev-server"
  }

运行 npm run start 发现没有自动创建index.html 不能直观看到我们代码在浏览器的执行。 在src目录下创建html模板 index.html 并安装 html-webpack-plugin 插件
终端运行: npm i -d html-webpack-plugin
在webpack.config.js 下添加插件配置plugins

const path = require("path");
const HtmlWebPackPlugin = require("html-webpack-plugin");
module.exports = {
  mode: "development", //打包模式
  entry: "./src/index.js", //入口文件指定
  output: {
    //出口文件配置 配置出口打包路径
    filename: "build[hash:8].js", //打包的文件名称 filename: "build[hash:8] 添加哈希值
    path: path.resolve(__dirname, "build") //resolve绝对路径引入
  },
  devServer: {
    //开发服务器配置
    contentBase: "./build", //指向打包目录
    port: 3000, //服务端口号
    progress: true, //打包进度
    open: true, //是否打开浏览器
    compress: false //是否压缩
  },
  //插件
  plugins: [
    //数组形式 存放所有的webpack插件
    new HtmlWebPackPlugin({
      filename: "index.html", //生成打包文件名
      template: "./src/index.html", //模板路径
      minify: { //生产模式可以进行配置
        removeAttributeQuotes: true, //删除 html文件双引号
        collapseWhitespace: true //折叠控行
      },
      hash:true, //添加哈希值
    })
  ]
};

终端执行打包测试:npm run build (build目录下生成了我们想要生成的index.html文件)

样式的配置 webpack配置css模块:

配置样式需要一个合适loader,loader会将我们的样式文件解析成模块(module)
终端:npm i -d --save css-loader style-loader
如何使用样式loader进行配置呢? 我们先在src下建index.css并给body赋予简单样式 在webpack.config.js 进行简单配置
css-loader主要解析我们样式中@import语法,style-loader是吧css样式插入head标签中.

+ module: {
    //添加模块模块是对象
    rules: [
      //规则 css-loader主要解析我们样式中@import语法
      {
        test: /.css$/,
        use: ["style-loader", "css-loader"] //执行顺序是重右向左执行 - >重下到上
      }
    ]
  }

在index.js中引入样式文件 import "./index.css"
终端运行:npm run start 样式生效了同样我们也有对应的less less-loader
终端:npm i -d --save less less-loader 在这里说一下loader 的另一种写法对象写法可以给loader添加一些属性options

+ module: {
    //添加模块模块是对象
    rules: [
      //规则 css-loader主要解析我们样式中@import语法
      {
        test: /.css$/,
        use: [ 
           {
            loader: "style-loader",
            options: {
              insertAt: "top" //把标签插入顶部
            }
          }, 
          "css-loader"
          ] //执行顺序是重右向左执行 - >重下到上
      },
      {
        test: /.less$/,
        use: [
            {
            loader: "style-loader",
            options: {
              insertAt: "top" //把标签插入顶部
            }
          }, 
          "css-loader",
          "less-loader"
        ] //执行顺序是重右向左执行 - >重下到上
      }
    ]
  }

css 样式的抽离 安装抽离插件 mini-css-extract-plugin npm i -d --save mini-css-extract-plugin
引入插件并在配置文件中进行配置

const path = require("path");
const HtmlWebPackPlugin = require("html-webpack-plugin");
const MinCssExtractPlugin = require("mini-css-extract-plugin"); //抽离css插件
module.exports = {
 mode: "development", //打包模式
 entry: "./src/index.js", //入口文件指定
 output: {
   //出口文件配置 配置出口打包路径
   filename: "[name][hash:8].js", //打包的文件名称 filename: "build[hash:8] 添加哈希值
   path: path.resolve(__dirname, "build") //resolve绝对路径引入
 },
 devServer: {
   //开发服务器配置
   contentBase: "./build", //指向打包目录
   port: 3000, //服务端口号
   progress: true, //打包进度
   open: true, //是否打开浏览器
   compress: false //是否压缩
 },
 //插件
 plugins: [
   //数组形式 存放所有的webpack插件
   new HtmlWebPackPlugin({
     filename: "index.html", //生成打包文件名
     template: "./src/index.html", //模板路径
     minify: {
       removeAttributeQuotes: true, //删除 html文件双引号
       collapseWhitespace: true //折叠控行
     },
     hash: true //添加哈希值
   }),
   new MinCssExtractPlugin({
     filename: "mian.css"
   })
 ],
 module: {
   //添加模块模块是对象
   rules: [
     //规则 css-loader主要解析我们样式中@import语法
     {
       test: /.css$/,
       use: [
         MinCssExtractPlugin.loader, //创建link标签放入到main.css里
         "css-loader"
       ] //执行顺序是重右向左执行 - >重下到上
     },
     {
       test: /.less$/,
       use: [
         MinCssExtractPlugin.loader, //创建link标签放入到main.css里
         "css-loader",
         "less-loader"
       ] //执行顺序是重右向左执行 - >重下到上
     }
   ]
 }
}

添加样式前缀 postcss-loader autoprefixer
npm i postcss-loader autoprefixer -d

 module: {
    //添加模块模块是对象
    rules: [
      //规则 css-loader主要解析我们样式中@import语法
      {
        test: /.css$/,
        use: [
          MinCssExtractPlugin.loader, //创建link标签放入到main.css里
          "css-loader",
          "postcss-loader"
        ] //执行顺序是重右向左执行 - >重下到上
      },
      {
        test: /.less$/,
        use: [
          MinCssExtractPlugin.loader, //创建link标签放入到main.css里
          "css-loader",
           "postcss-loader",
          "less-loader" 
        ] //执行顺序是重右向左执行 - >重下到上
      }
    ]
 }

注意 postcss-loader 需要添加一个配置文件否则不会生效更目录创建postcss.config.js

module.exports = {
  plugins: [require("autoprefixer")]
};

但是我们发现问题使用mini-css-extract-plugin插件导致我们css不会被压缩。
npm 官网有给出To minify the output, use a plugin like optimize-css-assets-webpack-plugin. Setting optimization.minimizer overrides the defaults provided by webpack, so make sure to also specify a JS minimizer:参考链接

要使用optimize-css-assets-webpack-plugin 插件接下来我们安装配置一下.
npm i -d optimize-css-assets-webpack-plugin

const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); //压缩js
//配置文件中添加优化项
optimization: {
    minimizer: [new OptimizeCSSAssetsPlugin({})]
  }

使用optimize-css-assets-webpack-plugin我们发现js右不会被压缩 所以要使用uglifyjs-webpack-plugin --save-dev $ npm install uglifyjs-webpack-plugin --save-dev 配置产考链接

const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); //压缩js
//配置文件中添加优化项
optimization: {
    minimizer: [new OptimizeCSSAssetsPlugin({}),new UglifyJsPlugin()]
  }
语法的转换 babel

在index.js 里写点es6语法箭头函数

let fn = () => {
  console.log("es6 webpack");
};
fn();

终端执行: npx webpack 查看打包文件

--我们发现打包出来的仍然是es6语法这个时候我们需要一个loader 进行转换 babel-loader babel @babel/core (babel/core是@babel-loader的核心组件转化模块@babel/preset-env) 参考链接 终端运行:npm i -d babel-loader babel @babel/core @babel/preset-env 在module添加配置

 //在rules下添加配置
 {
        test: /.js$/,
        use: [
          {
            loader: "babel-loader",
            options: {
              //转化es5语法--presets预设
              presets: ["@babel/preset-env"]
            }
          }
        ]
      },

终端运行:npm run build

发现可以已经转换es6语法 但是仅仅这样不能转换es6高阶语法比如一些特殊的类函数

class Test {
  // new Test() a =1 实例上添加a属性 这个语法属于es7语法打包时发现并不能解析
  a = 1;
}

终端运行:npm run build 发现报错提示安装 @babel/plugin-proposal-class-properties

那我们按照要求按照一下插件 npm i -d @babel/plugin-proposal-class-properties 并进行一次配置

 //在rules下添加配置
 {
        test: /.js$/,
        use: [
          {
            loader: "babel-loader",
            options: {
              //转化es5语法--presets预设
              presets: ["@babel/preset-env"],
               plugins: ["@babel/plugin-proposal-class-properties"]
            }
          }
        ]
      },

还有一种写法 装饰器@Log打包也是不被解析的 在js 添加

按照错误提示安装decorators-legacy 参考链接 安装官方给出配置添加

 //在rules下添加配置
 {
        test: /.js$/,
        use: {
          {
            loader: "babel-loader",
            options: {
              //转化es5语法--presets预设
              presets: ["@babel/preset-env"],
               plugins: [ //这里要注意添加顺序
                 ["@babel/plugin-proposal-decorators", { legacy: true }],
                ["@babel/plugin-proposal-class-properties", { loose: true }]]
            }
          }
    
      },

转化完语法接下来看一下babel语法的校验 @babel/plugin-transform-runtime @babel/runtime参考链接

  {
        test: /.js$/,
        use: {
          loader: "babel-loader",
          options: {
            //转化es5语法--presets预设
            presets: ["@babel/preset-env"],
            plugins: [
              ["@babel/plugin-proposal-decorators", { legacy: true }],
              ["@babel/plugin-proposal-class-properties", { loose: true }],
              [
                "@babel/plugin-transform-runtime",
                {
                  absoluteRuntime: false,
                  corejs: false,
                  helpers: true,
                  regenerator: true,
                  useESModules: false
                }
              ]
            ]
          }
        },
        include: path.resolve(__dirname, "src"), //只找__dirname - >src
        exclude: /node_modules/ //忽略node_modulse
      },

includes 实例方法不被解析 需要一个补丁模块@babel/polyfill
npm install --save @babel/polyfill Babel includes a polyfill that includes a custom regenerator runtime and core-js. 使用可以直接在js 里引入即可。
接下来看一下代码校验ESLint代码校验工具参考链接 终端安装 npm i -d eslint eslint-loader 根据项目需求下载对应的eslintrc.json 下载链接

 //代码校验eslint
      {
        test: /.js$/,
        use: {
          loader: "eslint-loader",
          options: {
            enforce: "pre" //强制执行顺序
          }
        }
      },

DEMO

本文回顾 1、webpack基本功能 build.js 打包的原理及源码分析 2、webpack基础配置及常用插件配置安装 3、loader的使用与配置样式的处理 4、webpack优化项的简单使用 5、babel语法转换与使用 babel语法校验 . 完成以上我相信大家可以掌握并搭建简单webpack项目。

第二章我们将讲解webpack 其他组件的配置及webpack优化项 webpack图片处理 多入口应用)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/7312.html

相关文章

  • Webpack 4.X 从入门精通 - devServer与mode(三)

    摘要:同时它还提供了自动刷新热更新等功能,使开发变得非常方便。的到来减少了很多的配置,它内置了很多的功能。 上一篇文章里详细介绍了一下插件的用法,这一篇文章接着丰富module.exports里的属性。如今的前端发展已经非常迅速了,伴随而来的是开发模式的转变。现在已经不再是写个静态页面并放在浏览器里打开预览一下了。在实际的开发中会经常需要使用http服务器,比如之前的ajax,想要看到效果就...

    王伟廷 评论0 收藏0
  • Webpack 4.X 从入门精通 - loader(五)

    摘要:处理与的语法大部分已经被各在浏览器所支持,当然除了万恶的,但是部分新增很遗憾并不被浏览器所支持比如内置对象新增的一些方法和对象等。但是在这里却不需要,是因为的里已经把内容添上了,就不需要创建文件了源码下载下一篇从入门到精通第三方库六 通过上一篇文章相信大家已经明白了loader的概念。那这篇文章继续介绍一些常用loader,并展现它的强大之处 处理less less与sass的功能都一...

    Me_Kun 评论0 收藏0
  • Webpack 4.X 从入门精通 - module(四)

    摘要:这就需要把文件单独拎出来,那需要一个插件来配合才能完成版本需要以上,低版本请使用使用步骤安装在里引入模块写入陈学辉文件目录会放入里写入代替执行命令后可以看到目录里已经多了一个文件夹,这个文件夹里放了一个文件。 概念 在webpack中任何一个东西都称为模块,js就不用说了。一个css文件,一张图片、一个less文件都是一个模块,都能用导入模块的语法(commonjs的require,E...

    harryhappy 评论0 收藏0
  • Webpack 4.X 从入门精通 - 第三方库(六)

    摘要:在开发的时候会时常用到第三方的库或者框架,比如耳熟能详的。使用第三方库在入口文件当中直接导入安装目录结构如图内容如下内容如下陈学辉内容如下这是自带的内容如下内容如下引入后打开页面会看到最后一个标签有了一个绿色的背景。 在开发的时候会时常用到第三方的库或者框架,比如耳熟能详的jquery。借助它们能提高开发效率,但是如何在webpack中使用呢。这篇文章介绍两个东西,如何使用第三方库以及...

    dunizb 评论0 收藏0
  • Webpack入门精通1

    前言 什么是webpack 本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。webpack 有哪些功能(代码转换 文件优化 代码分割 模块合并 自...

    wangbinke 评论0 收藏0

发表评论

0条评论

SunZhaopeng

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<