webpack 4.0 新手指南

1,379 阅读10分钟

特别注意:webpack 4.0 和 3.0 差别很大,该文档主要是 关于 webpack 4.0

前言

1、背景

网页中会引用的常见的静态资源?

js、

css、.css .sass .scss .less

images、

字体文件、

模板文件

网页中引入静态资源多了有什么问题?

1.网页加载速度慢,因为我们发起了很多次的二次请求

2.要处理错综复杂的依赖关系

如果解决上述两个问题?

1.样式和js :合并、压缩

2.图片:尺寸小的图片base64编码

3.使用requireJs 也可以使用webpack 解决各个包之间的复杂依赖关系

2、webpack是什么

是什么?

前端资源的 加载/打包 工具, 将多种静态资源(css,js,less等) 转换 成一个静态文件(static,assets),减少了页面的请求,也是项目构建工具,通过该工具,可以实现对项目的 加载打包

可以做的事情:

代码转换、(转换成浏览器能识别的形式) 文件优化、(压缩代码体积,合并文件) 代码分割、代码合并、自动刷新、代码校验、自动发布

技能基础

node基础,会npm使用

es6语法

学习目标

webpack常用配置

掌握webpack流程

基本使用

1.安装

在node.js 环境下,创建一个新目录,初始化npm,然后开始安装

npm init -y

在本地安装 webpack , webpack-cli

npm install webpack webpack-cli --save-dev

2.创建文件基本结构

/src “源”代码是用于书写和编辑的代码。

/dist “分发”代码是构建过程产生的代码最小化和优化后的“输出”目录,最终将在浏览器中加载

  • dist 压缩后要发布的文件
  • src 手写的 源代码 和 资源库
    • css 项目用到的手写css文件库
    • images 项目用到的图片库
    • js 项目用到的js库
    • index.html 项目入口文件
    • main.js 项目 js 入口文件
  • webpack.config.js 打包配置文件

3.开始写项目

3.1原则:

1、手写文件全部在 src 文件夹中

2、逻辑都写入 main,js 中 、所有其他需要用到的资源 都引入 main.js 中

3、结构写在 index.html 中

4.手写好的代码,一定要 打包编译后 才可以使用,才能被浏览器识别

3.2打包编译

作用: 将手写的 src 中的 文件和代码,通过打包编译,进行压缩优化,同时编译成 浏览器能理解的语法

打包命令:

npx webpack

如果有配置文件,根据配置文件打包,如果没有配置文件,默认找到 src/index 打包到 dist/main.js

打包指定目录下的指定文件,并以指定的目录和指定的文件名输出

npx webpack ./src/index.js -o ./dist/bundle.js --mode development

根据某个配置文件打包:

npx webpack --config webpack.config.js

开发模式下打包(未压缩)

npx webpack --mode development

生产模式下打包(压缩的)

npx webpack --mode production

以上的打包命令,可以通过在 package.json 添加一个 npm 脚本(npm script):作为运用打包的快捷方式

"scripts": {
      "test": "echo \"Error: no test specified\" && exit 1",
+     "build": "webpack --mode production""dev": "webpack --mode development"
    },

每次 手写的代码 修改后,都需要执行 一次 打包命令,将之前打包生成的 bundle.js 替换掉,浏览器效果才会发生变化。

打包流程: 当我们在控制台,直接输入 webpack 命令执行的时候,webpack做了以下几步: 1.首先,webpack发现,我们并没有通过命令的形式,给他指定入口和出口 2.webpack就会去 项目 的根目录中,查找一个叫做 ‘webpack.config.js’ 的配置文件 3.当找到配置文件后,webpack会去解析这个 配置文件,当解析执行完配置文件后,就得到了配置文件中,导出的配置对象 4.当 webpack 拿到配置对象后,就拿到了 配置对象中,指定的 入口 和 出口,然后进行打包构建

3.3插件

想要webpack实现一些本身不具备的功能,需要借助插件来完成

1.下载 install npm install --save-dev 插件名

  1. 导入插件并且修改配置
    webpack.config.js ①require ②plugins数组中,添加实例

3.使用 npm run build

常用插件:

  • 清理dist中无用的文件

在每次构建前清理 /dist 文件夹,是比较推荐的做法,因此只会生成用到的文件。 clean-webpack-plugin 是一个比较普及的管理插件。

npm install --save-dev clean-webpack-plugin
+ const { CleanWebpackPlugin } = require("clean-webpack-plugin");

plugins: [
+     new CleanWebpackPlugin(),
      new HtmlWebpackPlugin({
        title: 'Output Management'
      })
    ],

npm run build 后,dist中没有垃圾文件

  • 自动打包编译的功能

webpack-dev-server 每次更新代码后,使代码可以自动打包编译

npm install --save-dev webpack-dev-server

webpack.config.js

devServer: {
+     contentBase: './dist'
+   },

以上配置告知 webpack-dev-server,在 localhost:8080 下建立服务,将 dist 目录下的文件,作为可访问文件。 www.webpackjs.com/configurati…

添加一个 script 脚本,可以直接运行开发服务器(dev server):

"start": "webpack-dev-server --open",

-- hot 热更新(不重新打包为新的版本,只替代更新的部分),页面不刷新的情况下,就可以应用新代码 --port 3000 修改端口号

1.3 使用 在命令行中运行 npm start,就会看到浏览器自动加载页面。

如果现在修改和保存任意源文件,web 服务器就会自动重新加载编译后的代码。

webpack-dev-server帮我们打包生成的bundle.js文件,并没有存到 实际的 物理磁盘上(/dist,一个文件夹就是一个物理磁盘);而是,直接托管到了 电脑的内存 中,所以,我们在 项目根目录中,根本找不到 这个打包好的 bundle.js;我们可以认为,webpack-dev-server 把打包好的 文件,以一种虚拟的形式,托管到了 我们项目的 根目录中,虽然我们看不到它,但是,可以认为,和dist src node_modules 平级,有一个看不见的文件,叫做bundle.js, 这样做的原因是 提交速度快 , 如何在文件中引用这个生成的bundle.js 呢?利用下面的插件即可

webpack 模块打包器,只是打包的功能。所以每次修改了代码,都需要手动重新打包 webpack-dev-serve 一个服务器插件,相当于webpack+apache,启动一个web服务并实时更新修改

  • html-webpack-plugin

该插件有两个作用:

1.自动在 内存 中,根据指定页面生成 一个内存 index.html 的页面(不在dist中,看不到) 2.打包后,相关引用关系(img等)和文件路径(打包后的bundle.js)都会按照正确的配置被添加进去

cnpm install  --save-dev  html-webpack-plugin
  const path = require('path');
  // 导入这个插件
+ const HtmlWebpackPlugin = require('html-webpack-plugin');

  module.exports = {
+   plugins: [
+     new HtmlWebpackPlugin({
       //指定模板页面,将来会根据 指定的 页面路径,去生成内存中的 页面
+       templat:path.join(_dirname,'./src/index.html'),
       //指定 生成页面的 名称
        filename:'index.html'
+     })
+   ]
  };

配置好,打包编译,即可自动打开这个 在内存中的index.html 页面。

3.4 loader

webpack 本身只能打包 javascript文件,其他资源,如css、字体、图片等,是没办法加载的。这就需要对应的loader 将资源转化,再引入加载。

1.下载相应的loader npm install --save 包名 2.配置好 webpack.config.js配置
3.引入资源包(css文件、字体文件、图片文件) 使用 import

webpack处理第三方文件类型的过程:

1.发现这个 要处理的文件不是js文件, 然后就去配置文件中,查找有没有对应的第三方loader规则, 2.如果能找到这个对应的规则,就会调用 对应的 loader处理 这种文件类型; 3.在调用loader 的时候,是从后向前调用的; 4.当最后一个 loader 调用完毕,会把 处理的结果,直接交给 webpack 进行打包合并,最终输出到 bundle.js 中去

  • 1.下载相应依赖

npm install --save 包名
npm install --save-dev 包名 dev 是 develop(开发) 的缩写, devDependencies  开发环境的依赖


//编译css
cnpm install --save-dev style-loader css-loader
cnpm install --save-dev less-loader 
cnpm install --save-dev sass-loader
//识别url地址(编译字体图标和图片)
cnpm install --save-dev url-loader file-loader
  • 2.配置匹配规则

在 module对象上的 rules 属性,这个 rules 的数组中,存放了 所有的第三方文件的匹配 和处理规则

webpack.config.js配置

const path = require('path');

module.exports = {
  module:{
    rules:[
      { test:/\.css$/, use: ['style-loader','css-loader'] },
      { test:/\.less$/, use: ['style-loader','css-loader', 'less-loader'] },
      { test:/\.scss$/, use: ['style-loader','css-loader', 'sass-loader'] },
      { test:/\.(jpg|png|gif|bmp|jpeg)$/, use: 'url-loader' },
      { test:/\.(ttf|eot|svg|woff|woff2)$/, use: 'url-loader' },
    ]
  }
};
  • file-loader 是 url-load 依赖的包,所以不需要写在匹配规则里

给loader传参:匹配规则里的loader都可以被传参,传参方式和在url中传参一样,不过参数是固定写法

 { test:/\.(jpg|png|gif|bmp|jpeg)$/, use: 'url-loader?limit=7631 & name=[name].[ext]' },

关于url-loader的 limit 值: limit 给定的值,是图片的大小,单位是byte, 如果我们引用的图片,大于或者等于 给定的limit值,则不会被转为base64 格式的字符串,如果 图片小于给定的 limit值,则会被转为base64格式的字符串。 防止图片重名,打包编译后的图片的名字会自动被改为哈希值,如果想让图片名称和后缀名不变,可以设置参数 name=[name].[ext]。如果既不想重名,又想保留原来的值: name=[hash:8]-[name].[ext]

  • 3.引入相应文件

关于import

  1. js文件,因为会向外暴露一个变量,所以引入的时候 需要 一个 变量 来承接,以防冲突

非js文件,没有这个问题,所以直接导入即可 2.如果要通过路径的形式,去引入node_modules中相关的文件,可以直接省略 路径前面的 node_modules 这一层目录,直接写 包的名称,然后后面跟上具体的文件路径

import $ from 'jquery';
import './css/style.css';
import Icon from './icon.png';

import 'bootstrap/dist/css/bootstrap.css'

babel

处理高级es6 语法的loader 在webpack中,默认只能处理一部分 es6 的新语法,一些更高级的 es6语法 或者 es7语法,webpack是处理不了的; 这时候,通过babel,可以帮我们将 高级的语法转换为 低级的语法,当 babel 把 高级语法转换为 低级的语法之后,会把结果交给 webpack 去打包到 bundle.js中

1.在 webpack 中,可以运行如下两套命令,安装两套包,去安装 babel 相关的loader功能; 1.1 第一套包:

cnpm i babel-core babel-loader babel-plugin-transform-runtime --save-dev

1.2 第二套包:

cnpm i babel-preset-env  babel-preset-stage-0 --save-dev

2.打开 webpack 配置文件,在module 节点下的 rules 数组中,添加一个 新的 匹配规则:

test:/ \.js$ /, use: 'babel-loader', exclude: / node_modules /}

2.2 注意:在 babe 的loader规则的时候,必须 把 node_modules 目录,通过 exclude 选项排除掉,原因有两: 2.2.1 如果 不排除 node_modules, 则babel会把 node_moduless 中所有的第三方 js文件,都打包编译,这样,会非常消耗 cpu,同时,打包速度非常慢 2.2.2 哪怕 babel 把 node_modules 中的js都编译转换完毕了,但是 项目也无法正常运行。

3.在 项目的 根目录中,新建一个 叫做 .babelrc 的 babel 配置文件,这个配置文件,属于 json格式,所以,在写.babelrc 配置的时候,必须符合json语法规范:不能写注释,字符串必须用双引号 3.1 在 .babelrc 写如下的配置: 大家可以把preset 翻译成 【语法】的意思 { “presets”:[“env”,“stage-0”], “plugins”:["transform-runtime" ] }

4.配置文件

默认状态下,webpack 不需要配置文件,默认了入口点:src/index ,并且将结果 dist/main.js 缩小并优化生产。 如果要扩展功能,在根文件夹中创建一个文件 webpack.config.js ,手写相关配置。 主要包含以下几部分内容:

webpack.config.js

const path = require('path');

module.exports = {
// 入口,表示要使用webpack 打包哪个文件
  entry: './src/index.js',
// 输出文件的相关配置
  output: {
    // 指定 输出文件 的名称
    filename: 'bundle.js',
    // 出口指定打包好的文件,输出到哪个目录中去
    path: path.join(__dirname, './dist')
  },
  plugins: [
+     new CleanWebpackPlugin(),
      new HtmlWebpackPlugin({
        title: 'Output Management'
      })
   ],
  module:{
    rules:[
      { test:/\.css$/, use: ['style-loader','css-loader'] },
      { test:/\.less$/, use: ['style-loader','css-loader', 'less-loader'] },
      { test:/\.scss$/, use: ['style-loader','css-loader', 'sass-loader'] },
      { test:/\.(jpg|png|gif|bmp|jpeg)$/, use: 'url-loader' },
      { test:/\.(ttf|eot|svg|woff|woff2)$/, use: 'url-loader' },
    ]
  } 
};

选择配置文件打包: npx webpack --config webpack.config

问题解决:

  1. json文件中不能添加注释
  2. 学会查看命令行报错信息,一般会报错
  3. ** 不是内部或外部命令,也不是可运行......
  • 如果是全局安装的,查看是否是环境变量的问题
  • 如果是本地安装的,查看是否是node_module 文件丢失
  • 如果还不行,删除node_module,重新安装

4.如果安装到一半,暂停安装,再次安装后,很快就安完,但是运行时容易出错,就删掉node_modules 重新安装

5.如果某次打包失败,解决方案:删除已经下载好的node_modules包,重新npm install,再重新打包 npm run build 即可

6.peerDependencies WARNING less-loader@^5.0.0 requires a peer of less@^2.3.1 || ^3.0.0 but none was installed 版本不兼容导致的,重新下载 提示的loader

7. Cannot find module '@babel/core' 安装提示 下载所需要的 module