Webpack入门到精通(1)

栏目: 编程语言 · 发布时间: 4年前

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

前言

什么是webpack 本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。

webpack 有哪些功能(代码转换 文件优化 代码分割 模块合并 自动刷新 代码校验 自动发布)

首先学习webpack 需要有简单的node 基础 ,打开node 官方网站进行安装node, http://nodejs.cn/ 下载最新版node包并进行安装。

学习目标:

  1. webpack 常见配置 webpack高级配置
  2. webpack优化策略
  3. AST抽象语法树
  4. webpack中的Tapable
  5. 掌握webpack流程 手写 webpack
  6. 手写webpack中常见的loader
  7. 手写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(如图:)

Webpack入门到精通(1)

执行顺序:(默认找node_modules--->bin文件 --> webpack文件 )

Webpack入门到精通(1)

这里我们明白了安装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:是一个执行函数)

Webpack入门到精通(1)

接收到modules 里 先定义一个缓存对象 installedModules先定一个缓存目的是如果我当前模块加载完成没有必要再进行加载

webpack_require实现了一个require方法因为浏览器无法直接执行node的require方法 (详解如图)

Webpack入门到精通(1)

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

Webpack入门到精通(1)

Webpack入门到精通(1)

Webpack入门到精通(1)

终端运行: 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

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 查看打包文件

Webpack入门到精通(1)

--我们发现打包出来的仍然是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

Webpack入门到精通(1)

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

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

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

Webpack入门到精通(1)

那我们按照要求按照一下插件 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 添加

Webpack入门到精通(1)

按照错误提示安装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图片处理 多入口应用)

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

极致产品

极致产品

周鸿祎 / 中信出版社 / 2018-6 / 58.00

周鸿祎作为*知名的产品经理之一,一手打造了众多国民级的产品。他关于打造爆款的理念,比如刚需、高频、“小白”思维等,已成为网络热词而被广泛接受。 本书是周鸿祎首次系统总结其20年产品经理的心得,不仅将以往的理念进行总结、归纳,而且在与包括各方面创业者、产品经理的碰撞后,将其观念进一步升华,成为迄今为止首部将其产品理念倾囊相授的作品。一起来看看 《极致产品》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具