webpack 快速入门教程

webpack 是什么

webpack 是一种前端资源构建工具,一个静态模块打包器(module bundler)。

在 webpack 看来, 前端的所有资源文件(js/json/css/img/less/…)都会作为模块处理。 它将根据模块的依赖关系进行静态分析,打包生成对应的静态资源(bundle)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6jcc1KKp-1595555820303)(/Users/mxj/百度云同步盘/学习笔记/前端全栈/img/image-20200406095604708.png)]

官方中文文档参考:https://www.webpackjs.com/

模块打包,通俗地说就是:找出模块之间的依赖关系,按照一定的规则把这些模块组织合并为一个JavaScript文件。

webpack 的五个核心感念

名称描述
entry入口(Entry)指示 webpack 以哪个文件为入口起点开始打包,分析构建内部依赖图。
output输出(Output)指示 webpack 打包后的资源 bundles 输出到哪里去,以及如何命名。
loaderLoader(加载器) 让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)
plugins插件(Plugins)可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩, 一直到重新定义环境中的变量等。
mode通过选择 developmentproduction 之中的一个,来设置 mode 参数,你可以启用相应模式下的 webpack 内置的优化

webpack 安装与命令行打包

Webpack依赖Node.js,所以首先你要确保安装了 node.js。

node 官网

Webpack的安装分为全局安装与本地安装,推荐使用本地安装。

全局安装的Webpack,在任何目录执行webpack命令都可以进行打包。而本地安装的Webpack,必须要找到对应node_modules下的webpack命令才能执行(在使用npx或package.json的scripts的时候,会自动帮助我们寻找)。

全局安装

# 全局安装最新稳定版本
  npm install webpack webpack-cli -g

# 全局安装指定版本
  npm install webpack@4.43.0  webpack-cli@3.3.12 -g

# 全局安装指体验版本,目前(2020-7-10)体验版本是webpack5
  npm install webpack@next webpack-cli -g

本地安装

# 本地安装最新稳定版本,该命令是npm install webpack webpack-cli --save-dev的缩写
  npm i webpack webpack-cli -D

全局安装与本地安装的Webpack是可以共存的。在大多数前端项目开发的时候,是需要本地安装的。因为只进行全局安装的话,可能因为版本不一致的问题导致本地项目跑不起来。

本地安装的Webpack,如果不想拼接路径,我们可以使用命令npx webpack,或者在package.json文件里写入下面的命令并执行npm run dev。这两种方式都会自动执行node_modules下的webpack命令,不需要我们把路径拼接上。

 // ...
  "scripts": {
    "dev": "webpack"
  },
  // ...

使用方法

初始化一个npm项目并使用默认参数创建package.json文件。

npm init -y

安装了指定版本的webpack与webpack-cli。

npm install --save-dev webpack@4.43.0    webpack-cli@3.3.12   

webpack是webpack核心包,webpack-cli是命令行工具包,在用命令行执行webpack的时候需要安装。

因为浏览器不支持原始 ES6 模块,所以不能直接将 ES6 的 JS 文件导入 html。我们可以通过Webpack把这两个文件打包成一个JS文件来解决这个问题。Webpack打包后,代码里就没有这种模块化语法了。

打包命令

a.js

import { name } from './b.js';  
console.log(name);

b.js

export var name = 'Jack';

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script src="./bundle.js"></script>
</body>
</html>

执行打包命令

npx webpack a.js -o bundle.js  

打包之后就可以把合并之前的文件删除了,即a.js、 b.js。

打包后的bundle.js代码目前是压缩后的,后面会讲解怎样不压缩打包后的代码。

我们在执行上面命令的时候,命令行控制台会出现警告信息,告诉我们没有设置’mode’项,Webpack将会使用默认的’production’。我们可以在上面的命令后面配上’mode’项,但当命令参数过长的时候,使用起来就会不方便。此时,我们可以选择使用Webpack的配置文件。

image-20200723204755197

webpack 配置文件

Webpack默认的配置文件是项目根目录下的webpack.config.js,在我们执行下方命令的时候,

npx webpack  

Webpack会自动寻找该文件并使用其配置信息进行打包。如果不存在会报错

image-20200723205058065

我们可以手动创建 webpack.config.js 文件。

  var path = require('path');  
  module.exports = {
    entry: './a.js',
    output: {
      path: path.resolve(__dirname, ''),
      filename: 'bundle.js'
    },
    mode: 'none'
  };

命令行执行npx webpack后,Webpack就开始打包了。配置文件里的代码解释:

因为Webpack是基于Node.js执行的,所以可以使用Node的功能。path是Node.js里的路径解析模块,你可以将其看成是一个JS普通对象,该对象有一些方法可以供我们使用。我们现在使用了其resolve方法,该方法的作用是将方法参数解析成一个绝对路径返回。__dirname是Node.js的一个全局变量,表示当前文件的路径。这样,path.resolve(__dirname, ”)表示的其实就是当前文件夹根目录的绝对路径。

module.exports是CommonJS模块导出语法,导出的是一个对象,该对象的属性就是Webpack打包要使用的参数。entry是Webpack构建的入口文件,我们的入口文件是a.js。output是打包后资源输出文件,其中path表示输出的路径,filename表示输出的文件名,现在我们把打包后的文件输出在当前目录的bundle.js。

mode是Webpack的打包模式,默认是’production’,表示给生产环境打包的。现在我们设置成’none’,这样代码就不会压缩了。

入口起点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EqXLDlTb-1595555820306)(/Users/mxj/百度云同步盘/学习笔记/前端全栈/自动化部署/img/webpack-tutorial-1024x454.png)]

图片里箭头开始的.js文件就是Webpack构建的资源入口,然后根据这个.js文件依赖的文件,把相关联的文件模块打包到一个.js文件,本质上来说,这个打包后得到的.js文件就是Webpack打包构建的资源出口。

当然,这个.js文件通常不是我们最终希望打包出来的资源,我们希望可以拆分成JS、CSS和图片等资源。

Webpack当然提供了这样的方法。在构建的时候,我们可以通过Webpack的预处理器loader和插件plugin等进行干预,把一个.js文件变成JS、CSS和图片等资源。

可以通过修改 webpack 配置的 entry 属性,来指定一个或多个入口路径。默认为 ./src。

webpack.config.js

module.exports = {
  entry: './path/to/my/entry/file.js' //入口路径
};

webpack 基础目录(context)

context 官方称为基础目录,在Webpack中表示资源入口entry是从哪个目录为起点的。context的值是一个字符串,表示一个绝对路径。

下面的配置表示从工程根目录下src文件夹下的js文件夹里的a.js开始打包。

var path = require('path');  
  module.exports = {
    context: path.resolve(__dirname, './src'),
    entry: './js/a.js',
    output: {
      path: path.resolve(__dirname, ''),
      filename: 'bundle.js'
    },
    mode: 'none'
  };

一般我们不会去设置context,在我们没有设置context的时候,它是当前工程的根目录。

资源入口 entry

Webpack资源入口entry代表的路径,是相对路径。目前我们使用的entry都是字符串形式的,其实它还可以是数组、对象和函数形式。

  • 字符串

    字符串形式的我们已经在之前使用过了,是最简单的形式,表示打包的入口JS文件。

  • 数组

    module.exports = {
        entry: ['core-js/stable', 'regenerator-runtime/runtime', './a.js'],
      };
    

    它表示的含义是数组最后一个文件是资源的入口文件,数组其余文件会预先构建到入口文件。

    上面的配置和下面是等效的

    a.js

      import 'core-js/stable';
      import 'regenerator-runtime/runtime';
    

    webpack.config.js

    module.exports = {
        entry: './a.js',
      };
    

    数组形式的入口本质还是一个入口。

  • 对象

    入口entry是对象形式的又称之为多入口配置,本质上打包后生成多个JS文件。

    var path = require('path');  
      module.exports = {
        entry: {
          app: ['core-js/stable', 'regenerator-runtime/runtime', './a.js'],
          vendor: './vendor'
        },
        output: {
          path: path.resolve(__dirname, ''),
          filename: '[name].js'
        },
        mode: 'none'
      };
    

    上方的配置分别从两个入口文件打包,每个入口文件各自寻找自己依赖的文件模块打包成一个JS文件,最终得到两个JS文件。

  • 函数

    函数形式的入口,Webpack取函数返回值作为入口配置,返回值是上述3种之一即可。

    函数形式的entry,可以用来做一些额外的逻辑处理,不过在自己搭脚手架的很少使用。

常见场景

分离 应用程序(app) 和 第三方库(vendor) 入口

webpack.config.js

const config = {
  entry: {
    app: './src/app.js',
    vendors: './src/vendors.js'
  }
};

多页面应用程序

webpack.config.js

const config = {
  entry: {
    pageOne: './src/pageOne/index.js',
    pageTwo: './src/pageTwo/index.js',
    pageThree: './src/pageThree/index.js'
  }
};

这个告诉 webpack 需要 3 个独立分离的依赖图(如上面的示例)。

在多页应用中,每当页面跳转时服务器将为你获取一个新的 HTML 文档。页面重新加载新文档,并且资源被重新下载。

输出

output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist。基本上,整个应用程序结构,都会被编译到你指定的输出路径的文件夹中。你可以通过在配置中指定一个 output 字段,来配置这些处理过程:

webpack.config.js

const path = require('path');

module.exports = {
  entry: './path/to/my/entry/file.js',
  output: {
    path: path.resolve(__dirname, 'dist'), //输出路径
    filename: 'my-first-webpack.bundle.js' //用于输出文件的文件名。
  }
};

配置 output 选项可以控制 webpack 如何向硬盘写入编译文件。注意,即使可以存在多个入口起点,但只指定一个输出配置。

publicPath

publicPath 指定静态资源路径,当使用 webpack 打包时会将打包文件放进指定的目录中。

当使用 webpack-dev-server 时可以不用设置publicPath,因为该插件内置的库会自动在根目录下生成 index.html。

webpack-dev-server 会把打包后的文件放到项目的根目录下,文件名是在output配置中的filename. 但是当有publicPath 配置的时候,就不一样了。Webpack 会把所有的文件打包到publicPath指定的目录下,就是相当于在项目根目录下创建了一个publicPath目录, 然后把打包成的文件放到了它里面,只不过我们看不到而已, 文件名还是output配置中的filename。

模式

提供 mode 配置选项,告知 webpack 使用相应模式的内置优化。

语法

module.exports = {
  mode: 'production'
};

或者从 CLI 参数中传递:

webpack --mode=production

支持以下字符串值:

选项描述
development会将 process.env.NODE_ENV 的值设为 development。启用 NamedChunksPluginNamedModulesPlugin
production会将 process.env.NODE_ENV 的值设为 production。启用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPluginUglifyJsPlugin.

loader

Loader是Webpack生态里一个重要的组成,我们一般称之为预处理器。

loader 用于对模块的源代码进行转换。loader 可以将文件从不同的语言(如 TypeScript)转换为 JavaScript,或将内联图像转换为 data URL。loader 甚至允许你直接在 JavaScript 模块中 import CSS文件!因为 webpack 只解析 js/json 格式的文件,所以当需要给 css、图片打包时需要用到 loader。

loader 可以使你在 import 或"加载"模块时预处理文件。

安装 loader

这里我们安装两个loader,分别是css-loader与style-loader。

其中css-loader是必需的,它的作用是解析CSS文件,包括解析@import等CSS自身的语法。它的作用也仅仅是解析CSS文件,它会把CSS文件解析后,以字符串的形式打包到JS文件中。不过,此时的CSS样式并不会生效,因为我们需要把CSS插入到html里才会生效。

此时,style-loader就来发挥作用了,它可以把JS里的样式代码插入到html文件里。它的原理很简单,就是通过JS动态生成style标签插入到html文件的head标签里。

npm install --save-dev css-loader
npm install --save-dev style-loader

// 合并写法
npm install -S css-loader style-loader 

在 webpack 的配置中 loader 有两个目标:

  1. test 属性,用于标识出应该被对应的 loader 进行转换的某个或某些文件。
  2. use 属性,表示进行转换时,应该使用哪个 loader。

webpack.config.js

const path = require('path');

const config = {
  output: {
    filename: 'my-first-webpack.bundle.js'
  },
  module: {
    rules: [
      { 
       test: /\.css/, //正则匹配将要打包的文件格式
       use: ['style-loader', 'css-loader'] //使用的加载器
      }
    ]
  }
};

module.exports = config;

可以看到,我们需要对配置项新增module,该项是一个对象,其rules里是我们对各个类型文件的处理规则配置。

use值是一个数组,每一项是一个loader。loader的执行顺序是从后向前执行,先执行css-loader,然后把css-loader执行的结果交给style-loader执行。

现在我们执行npx webpack来完成打包,然后在浏览器打开index.html,发现CSS生效了。

使用

  • webpack配置(推荐):在 webpack.config.js 文件中指定 loader。

  • 内联:在每个 import 语句中显式指定 loader。

    import Styles from 'style-loader!css-loader?modules!./styles.css';
    
  • cli

    你也可以通过 CLI 使用 loader:

    webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'
    

    这会对 .jade 文件使用 jade-loader,对 .css 文件使用 style-loadercss-loader

plugins

插件目的在于解决 loader 无法实现的其他事

webpack 插件是一个具有 apply 属性的 JavaScript 对象。apply 属性会被 webpack compiler 调用,并且 compiler 对象可在整个编译生命周期访问。

用法

由于插件可以携带参数/选项,你必须在 webpack 配置中,向 plugins 属性传入 new 实例。

配置

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin'); //通过 npm 安装
const webpack = require('webpack'); //访问内置的插件
const path = require('path');

const config = {
  entry: './path/to/my/entry/file.js',
  output: {
    filename: 'my-first-webpack.bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        use: 'babel-loader'
      }
    ]
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin(),
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
};

module.exports = config;

webpack 初体验

初始化配置

(1)初始化 package.json

npm init

(2)下载并安装 webpack

npm install webpack webpack-cli -g //全局安装
npm install webpack webpack-cli -D //局部安装

当电脑上全局安装 webpack 时也需要局部安装,因为在运行的项目所使用的 webpack 版本可能低于当前电脑中的版本,这时需要安装指定版本的 webpack

npm install webpack@1.1

编译打包应用

  1. 创建文件

  2. 运行指令

    开发环境指令:webpack src/js/index.js -o build/js/built.js --mode=development
    功能:webpack 能够编译打包 js 和 json 文件,并且能将 es6 的模块化语法转换成浏览器能识别的语法。
    
    生产环境指令:webpack src/js/index.js -o build/js/built.js --mode=production
    功能: 在开发配置功能上多一个功能,压缩代码。
    
  3. 结论

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

  4. 问题
    不能编译打包 css、img 等文件。
    不能将 js 的 es6 基本语法转化为 es5 以下语法。

开发环境基本配置

打包样式资源

(1)新建文件
在这里插入图片描述

(2)下载安装包

npm i css-loader style-loader less-loader less -D

(3)修改配置文件

// resolve 用来拼接绝对路径的方法 const { resolve } = require('path');
module.exports = {
// webpack 配置
// 入口起点
entry: './src/index.js', 
// 输出
output: {
// 输出文件名
filename: 'built.js',
// 输出路径
// __dirname nodejs 的变量,代表当前文件的目录绝对路径 path: resolve(__dirname, 'build')
},
// loader 的配置 module: {
rules: [
// 详细 loader 配置
// 不同文件必须配置不同 loader 处理 {
// 匹配哪些文件
test: /\.css$/,
// 使用哪些 loader 进行处理 use: [
// use 数组中 loader 执行顺序:从右到左,从下到上 依次执行
// 创建 style 标签,将 js 中的样式资源插入进行,添加到 head 中生效 'style-loader',
// 将 css 文件变成 commonjs 模块加载 js 中,里面内容是样式字符串 'css-loader'
] },
      {
        test: /\.less$/,
        use: [
'style-loader', 'css-loader',
// 将 less 文件编译成 css 文件 // 需要下载 less-loader 和 less 'less-loader'
] }
] },
// plugins 的配置 plugins: [
// 详细 plugins 的配置 ],
// 模式
mode: 'development', // 开发模式 // mode: 'production'
}

(4)运行指令 webpack

打包 html 资源

(1)新建文件
在这里插入图片描述

(2)安装命令

npm install --save-dev html-webpack-plugin

(3)修改配置

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
// loader 的配置 ]
}, plugins: [
// plugins 的配置
// html-webpack-plugin
// 功能:默认会创建一个空的 HTML,自动引入打包输出的所有资源(JS/CSS) // 需求:需要有结构的 HTML 文件
new HtmlWebpackPlugin({
// 复制 './src/index.html' 文件,并自动引入打包输出的所有资源(JS/CSS)
      template: './src/index.html'
    })
],
  mode: 'development'
};

(4)执行指令 webpack

打包图片资源

(1)新建文件
在这里插入图片描述

(2)下载安装包

npm install --save-dev html-loader url-loader file-loader

(3)修改配置

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
{
test: /\.less$/,
// 要使用多个 loader 处理用 use
use: ['style-loader', 'css-loader', 'less-loader']
}, {
// 问题:默认处理不了 html 中 img 图片 // 处理图片资源
test: /\.(jpg|png|gif)$/,
// 使用一个 loader
// 下载 url-loader file-loader loader: 'url-loader', options: {// 图片大小小于8kb,就会被base64处理
// 优点: 减少请求数量(减轻服务器压力)
// 缺点:图片体积会更大(文件请求速度更慢)
limit: 8 * 1024,
// 问题:因为url-loader默认使用es6模块化解析,而html-loader引入图片是commonjs // 解析时会出问题:[object Module]
// 解决:关闭 url-loader 的 es6 模块化,使用 commonjs 解析
esModule: false,
// 给图片进行重命名
// [hash:10]取图片的 hash 的前 10 位
// [ext]取文件原来扩展名
name: '[hash:10].[ext]'
} },
{
test: /\.html$/,
// 处理 html 文件的 img 图片(负责引入 img,从而能被 url-loader 进行处理) loader: 'html-loader'
} ]
}, plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
}) ],
  mode: 'development'
};

(4)运行指令: webpack

打包其他资源

其他资源值的是除 css、图片、html 之外的资源

(1)新建文件

在这里插入图片描述

(2)修改配置

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
},
// 打包其他资源(除了html/js/css资源以外的资源) {
// 排除 css/js/html 资源
exclude: /\.(css|js|html|less)$/, loader: 'file-loader',
options: {
          name: '[hash:10].[ext]'
        }
} ]
}, plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
})
],
  mode: 'development'
};    

devserver

修改配置

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
},
// 打包其他资源(除了html/js/css资源以外的资源) {
// 排除 css/js/html 资源
exclude: /\.(css|js|html|less)$/,
       loader: 'file-loader',
        options: {
          name: '[hash:10].[ext]'
        }
} ]
}, plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
}) ],
  mode: 'development',
   devServer: {
  // 项目构建后路径
  contentBase: resolve(__dirname, 'build'), // 启动 gzip 压缩
  compress: true,
  // 端口号
  port: 3000,
  // 自动打开浏览器
  open: true
  } };

运行指令: npx webpack-dev-server

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码搬运媛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值