webpack详解

webpack详解

定义:webpack 是一个基于 nodejs 的 JavaScript 的打包工具

作用:它会找到 JavaScript 文件以及其它的一些浏览器不能直接运行的文件(less , vue 等),并将其转换和打包为合适(浏览器认识)的格式.

在这里插入图片描述

webpack打包前的准备工作

1.- Nodejs + npm (必须环境)
2.- npm 国内速度优化
(1)第一种方法:手工设置 npm 下载代码时的服务器(镜像淘宝)

npm config set registry https://registry.npm.taobao.org

(2)第二种方法:上面的设置只是指定了 npm 包 js 代码的下载, 在某些库当中, 还要下载一些二进制文件, 这些如果也想从国内下载可以用下面这个npm工具
可以在做项目的时候, 针对当前项目做优化, 不会影响其他的项目
在这里插入图片描述
为项目生成镜像配置

npm i -g mirror-config-china

cd ~/my-project

mirror-config-china --registry=https://registry.npm.taobao.org

准备好这些便可以进行安装webpack

安装webpack

webpack 是一个基于 nodejs 的工具, 创建一个 node 项目进行开发 (npm项目)
1 初始化项目 新建项目文件夹webpack-demo, 并且在这个文件夹下面用终端运行下面命令初始化一个项目

npm init
// 请注意文件夹名最好只有 大小写字母,数字和减号,你原先已经排好的文件夹不要紧, 
//只需要在下面在创建一个合适的就好了,文件夹名字不得跟你要用到的包名一样,
//及最好不要使用中文,中文名字不能进行快速初始化项目

//也可以直接快速快速初始化
npm init -y

2 安装 webpack 在家可以使用下面的脚本将 webpack 安装在当前文件夹, 请确保终端打开的是 webpack-demo 文件夹.

npm install --save-dev webpack webpack-cli

添加命令 通过配置 package.json 文件里的 scripts 的方式使用

package.json中

"scripts": {
    "test": "webpack -v"
}

安装成功 在项目文件夹下打开命令行, 运行 npm run test 能够看见版本号代表安装成功

npm安装使用补充说明

  • 安装包时的心态问题
    国际间速度 / 学校内网
  • 创建一个 npm 项目命名的注意事项
    只能是 url friendly
    同名包,如果你只是本地开发, 没放上 npm 名字不要紧
    唯一需要注意的是, 不可以下载跟你项目名字相同的包, 这里指的是项目名称不能为webpack

使用 npm run 命令运行项目
在这里插入图片描述
npm 运行和直接运行的区别
如果是直接执行, 比如 webpack -v之类的命令, 系统会尝试在系统盘查找对应的工具
npm run test运行优先查找当前文件夹本地安装版本, 如果直接运行, 只会查找系统路径

npm install -S / npm install -D 的区别

  • npm install xxx 可以安装一个包,
  • –save / -S 作为生产环境依赖 会被记录到 package.json 的 dependencies 里面
  • –save-dev / -D 作为开发环境依赖 记录到 package.json 的 devDependencies 里面
  • 被记录过的所有依赖 都会在下次运行 npm install 全部安装
  • 开发环境依赖和生产环境依赖的区别在于, 如果你的包发布在 npm上, 别人安装, 只会安装到生产环境
    对于开发者本身无所谓, npm install 全部都会装上
  • -g 全局安装 装到计算机系统路径里面
    在这里插入图片描述

网速

在保证了基础网速的情况下 可以考虑使用 淘宝镜像

  • 最方便是上面那个 mirror-config-china
  • 可以使用命令进行修改 npm config set registry https://registry.npm.taobao.org
  • 使用一个工具 nrm

js模块化标准

很久很久以前, js 本身标准并没有模块概念, 但是程序员却又需要这个概念来组织代码, 很多牛人就各自开发了自己模块化系统

包括 CommonJS,AMD,CMD 等等

其中 nodejs 使用的是 CommonJS 的标准

  • 导出使用 module.exports
  • 导入使用require

ES6 模块化标准

  • 导出 export (如果是默认导出, 写成 export default)
  • 导入 import xxx from ‘路径’
  • 命名导出方式
// es6 的导出有两种情况
// 1. 命名式导出
export function minus(a, b) {
    return a - b
}
// ES6 标准的模块导入方式
// 针对命名的导出, 导入的时候必须按照导出的名字来命名
import abc from './minus'
// 实际上 import 进来的是所有 export 过的属性组成的对象, 从中间获取自己想要的对应变量
import {minus} from './minus'

console.log(abc);
console.log(minus);

默认的 export default 导出方式

function minus(a,b) {
    return a-b
}
// es6 的导出有两种情况
// 1 默认导出方式
export default minus
// ES6 标准的模块导入方式
// 针对 default 的方式进行的默认导出, 无论你在引入时使用什么名字
// 都可以将导出的东西获取回来
import abc from './minus'
console.log(111111);
console.log(abc);

webpack 初次体验

命令行打包

使用 webpack 将一个文件打包成另一个文件

  1. 创建一个被打包的文件
  2. 执行 webpack --entry ./index.js (如果是本地安装, 将命令配置到 package.json 里面)
  3. 只需要在 html 页面中引入文件就可以了

配置文件的使用方式

命令行方式不够灵活, 可以用配置文件的方式, 声明打包的设定

  1. 在目录下新建 index.js 文件
  2. 配置 webpack.config.js 文件, 放在项目根目录 (默认的位置默认的名字, 不要变)
const path = require('path');

module.exports = {
    entry: './index.js',					// 项目入口
    output: {
        filename: 'bundle.js',                  // 默认打包后的文件名 bundle.js
        path: path.resolve(__dirname, 'dist')   // 默认打包后的文件目录 dist
    }
};
  1. 在 package.json 配置 webpack 打包脚本
"scripts": {
    "test": "webpack -v",
    "build": "webpack --config webpack.config.js"
}
  1. 运行 npm 脚本
npm run build

成功的输出集成终端

> webpack-demo@1.0.0 build d:\itheima\course\VueBase\day5\02-源代码-Code\webpack-demo
> webpack --config webpack.config.js

Hash: 0bd066c0cbc0b4b08f18
Version: webpack 4.41.2
Time: 168ms
Built at: 2019-10-22 3:00:53 PM
    Asset       Size  Chunks             Chunk Names
bundle.js  930 bytes       0  [emitted]  main
Entrypoint main = bundle.js
[0] ./index.js 0 bytes {0} [built]

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/
  1. 在 html 引入代码

通用项目架构(常见的通用做法,项目的基础准备)

准备项目文件结构

注意: 注释前面带了加号(+)表示新增的或者手工创建的

- webpack-demo				//最外层, 项目根目录
	- dist					// + 输出目录,在浏览器中运行的目录
	- node_modules			// 安装 npm 包时自动生成
	- src					// + 开发目录
    - package.json			// 项目配置文件, npm init 初始化项目时自动生成
    - webpack.config.js		// + webpack配置文件

准备文件

dist/index.html 后面用来引入打包后的结果查看效果

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>webpack demo</title>
</head>
<body>
    <script src="./xxx.js"></script>
</body>
</html>

src/index.js(打包前的 js 文件)

// 写入到html的内容
var element = document.createElement("div");
element.innerHTML =  `<div>hello webpack</div>`;

document.body.appendChild(element);

配置webpack
webpack.config.js

const path = require('path');

module.exports = {
    entry: './src/index.js',					// 项目入口
    output: {
        filename: 'bundle.js',                  // 默认打包后的文件名 bundle.js
        path: path.resolve(__dirname, 'dist')   // 默认打包后的文件目录 dist
    }
};

准备使用打包后的 js 文件

dist/index.html`

注意:引用的资源都来自于打包后的 dist。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>webpack demo</title>
</head>
<body>
//引用打包后的js文件
    <script src="./bundle.js"></script>
</body>
</html>

开始打包
确认 package.json 脚本配置

"scripts": {
    "test": "webpack -v",
    "build": "webpack --config webpack.config.js"
}

在命令行中输入以下命令:

npm run build

集成终端输出结果:

> webpack-demo@1.0.0 build d:\itheima\course\VueBase\day5\02-源代码-Code\webpack-demo
> webpack --config webpack.config.js

Hash: adc6b8e1d8839a2e9655
Version: webpack 4.41.2
Time: 693ms
Built at: 2019-10-22 3:18:55 PM
    Asset      Size  Chunks             Chunk Names
bundle.js  1.01 KiB       0  [emitted]  main
Entrypoint main = bundle.js
[0] ./src/index.js 159 bytes {0} [built]

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You ca

注意:上述输出即是打包成功,配置的警告不影响打包结果,可忽略。

打包后dist的文件结构为

- webpack-demo
	- dist					// 输出目录,在浏览器中运行的目录
		- index.html		// 浏览器页面入口文件 现在是自己准备, 用来引入打包结果测试
		- bundle.js			// + 打包后的文件
	- // 其他文件

webpack 四个概念

概念一: 入口 (entry)

入口指示 webpack 应该使用哪个文件来作为打包的开始。拿到这个文件以后,webpack 会找出所有跟这个入口文件有关系的文件, 全部打包起来

import / require 等导入方式, 都是依赖关系的一种, webpack 会把所有关联的文件全部遍历出来

一个 entry 配置的最简单例子:

webpack.config.js文件

    module.exports = {
      entry: './src/index.js'
    };

概念二: 模块加载器 (loader)
模块加载器是webpack用于加载并处理其他非js文件的工具,比如自定义模板文件(Vue),css/less,图片,字体等资源文件。

注意:nodejs环境下默认只认识js文件。

加载 css

新增css文件

- webpack-demo
	- src
    	- index.js			
		- style.css	// + 新增css文件
    - // 其他文件

.red {
    color: red;
}

src/index.js

import './style.css';

// 写入到html的内容
var element = document.createElement("div");
element.innerHTML =  `<div class="red">hello webpack</div>`;
document.body.appendChild(element);

webpack 如何加载 css 文件?

安装两个加载器style-loader和css-loader,需要下载依赖包

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

配置 webpack , 让它懂得处理 css 文件
webpack.config.js

const path = require('path');

module.exports = {
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',                            
      path: path.resolve(__dirname, 'dist')    
    },
	
    // 模块加载器配置项
    module: {
        rules: [
            {
                test: /\.css$/,			// 匹配css扩展名文件
                use:[					// 配置loader加载器
                    'style-loader',		// 把css代码写入到网页中
                    'css-loader'		// 读取css的代码
                ]	
            }
        ]
    }
};

再次执行打包

npm run build

再次打开dist/index.html就能看能到红色的文字了。

加载less
新增less文件

- webpack-demo
	- src
    	- index.js			
		- style.css	
		- style.less // + 新增less文件
    - // 其他文件

src/style.less

body {
    div {
        background: yellow;
    }
}

src/index.js

import './style.css';
import './style.less';

// 写入到html的内容
var element = document.createElement("div");
element.innerHTML = `<div class="red">hello webpack</div>`;

document.body.appendChild(element);

webpack 如何加载 less 文件?

安装依赖包

npm install --save-dev less less-loader

配置 webpack 让它懂得如何处理 less 文件
webpack.config.js

const path = require('path');

module.exports = {
    // 其他配置...
	
    // 模块加载器配置项
    module: {
        rules: [
            // 这里上面有其他配置, 比如 css 之类...
            // 添加一个新的, 负责 less 文件
            {
                test: /\.less$/,		// 匹配less扩展名文件
                use:[				
                    'style-loader',		// 把less代码写入到网页中
                    'css-loader',		// 读取less的代码
                    'less-loader'		// 解释编译less代码
                ]	
            },
        ]
    }
};

执行打包

npm run build

补充: 加载 sass/scss

scss 是跟 less 类似的一种 css 预处理语言

如果遇到了, 也是一样的套路,

  • 引入 .scss 文件,
  • 装 loader 包,
  • 配置 webpack
import 'style.scss'
npm install sass-loader node-sass webpack --save-dev
module: {
    rules: [{
      test: /\.scss$/,
      use:[				
          'style-loader',	// 把scss代码写入到网页中
          'css-loader',		// 读取scss的代码
          'sass-loader		// 解释编译sass代码
      ]	
    }]
  }

加载图片/字体文件

在 nodejs 环境中所有的文件都是一个模块,需要导入才能使用,图片也不例外,比如我们想要在项目中引入一张图片。

- webpack-demo
	- images
		- logo.jpg
	- // 其他文件

src/index.js

require('./style.css');
require('./style.less');

import logo from './images/avatar.png'

// 写入到html的内容
// 添加显示图片
var element = document.createElement("div");
element.innerHTML = `
    <div class="red">hello webpack</div>
    <img src="${logo}"/>
    `;

document.body.appendChild(element);

style.css

@font-face {
    font-family: 'Myfont';
    src: url('./Goldie Rainbow.ttf');
}

body {
    font-family: 'Myfont';
    font-size: 30px;
}

注意:能被src调用说明import的logo是一个链接, 这是由 webpack 自动生成的。

安装依赖包

npm install --save-dev file-loader

配置 webpack

webpack.config.js

// 其他代码

module.exports = {
    // 其他配置...
	
    // 模块加载器配置项
    module: {
        rules: [
            // 其他配置...
			{
                test: /\.(png|svg|jpg|gif)$/,	// 匹配图片文件
                use: [
                    {
                        loader: "file-loader",              // 处理图片文件返回链接
                        options: {
                            outputPath: "images"            //  输出到dist下的images目录
                        }
                    } 
                ]
            },
            {
                test: /\.ttf$/,
                use: [
                    {
                        loader: "file-loader",              // 处理图片文件返回链接
                        options: {
                            outputPath: "assets"            //  输出到dist下的images目录
                        }
                    }
                ]
            }
        ]
    }
};

注意:处理图片时的配置稍微复杂点了,主要是file-loader可以搭配一些选项来使用,这些选项可以自行修改,参考文档

执行打包命令
npm run build

最新dist目录结构

- webpack-demo
	- dist
		- images
			- [hash字符串组成].jpg
		- assets
			- [hash字符串组成].ttf
		- bundle.js
		- // 其他文件

概念三: 插件系统

loader 加载器可以教会 webpack 处理不同文件,而插件则可以添加其他功能,比如优化压缩,提取 css / 自动生成 html 文件等等

其实插件并不是需要我们去理解怎么实现

主要使用插件的过程,应该是

  • 发现不对劲, 有需求 (我不希望css 被放在 js 文件里面)
  • 找插件进行实现
  • 按照文档使用,最终解决一开始提出的问题

提取css
通过dist文件结构我们发现打包出的文件中并没有独立的css文件,那么css样式被打包到哪里去了呢?

如果用编辑器打开bundle.js文件会发现内容有document.createElement(“style”)字样,其实css被打包到bundle.js中了。

那么假如 css 的内容很多,会让 bundle.js 文件变得很大,加载变慢,性能和体验都很差,所以我们需要把 css 的内容单独拆分到一个样式文件中,使用 webpack插件ExtractTextWebpackPlugin (对于webpack4+这个插件已经失效, 更换另一个)

最新提取 css 的插件
https://webpack.js.org/plugins/mini-css-extract-plugin/
在这里插入图片描述
安装依赖包

npm install --save-dev mini-css-extract-plugin

配置 webpack

webpack.config.js

const path = require('path');

// 插件的使用1. 引入插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
    // 项目入口
    entry: './src/index.js',
    output: {
        // 默认打包后的文件名 bundle.js
        filename: 'bundle.js',
        // 默认打包后的文件目录 dist
        path: path.resolve(__dirname, 'dist')
    },
    // 添加模块加载器的配置选项
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    // 提取css的插件使用第三步, 修改加载器
                    {
                        loader:MiniCssExtractPlugin.loader,
                        options:{
                            publicPath:'./style'
                        }
                    },	
                    'css-loader'
                ]
            },
            {
                test: /\.less$/,
                use: [
                   {
                        loader:MiniCssExtractPlugin.loader,
                        options:{
                            publicPath:'./style'
                        }
                    },	
                    'css-loader',
                    'less-loader'
                ]
            },
            {
                test: /\.(png|svg|jpg|gif)$/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            publicPath: './images/',
                            outputPath: 'images'
                        }
                    }
                ]
            }
        ],
    },
    // 添加插件配置选项
    plugins: [
        // 插件使用2. plugins 属性当中,创建实例, 按需添加参数
        // 这个插件如果不放任何参数, 默认生成 main.css 文件
        // 如果想要修改文件名, 就可以给一个配置对象, 然后里面添加 filename 属性
        new MiniCssExtractPlugin()
    ]
};

执行打包

npm run build

最新dist目录结构
在这里插入图片描述
需要把打包后的样式导入的index.html中
dist/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>webpack demo</title>
    <!-- + 导入样式 -->
    <link rel="stylesheet" href="./style/style.css">
</head>
<body>
    <script src="./bundle.js"></script>
</body>
</html>

自动生成html

在这里插入图片描述
目前我们都是在 index.html 中手动引入打包后的资源,这种引入方式有很多缺点,比如文件名依赖问题,假如 webpack 配置中的输出文件名修改了,需要及时在 index.html 中同步修改,再者每次新增文件都要引入一遍很繁琐。

可以使用 HtmlWebpackPlugin插件 自动引入打包后的资源文件到html文件,该插件需要指定一个html模板文件,并且会生成一个 index.html 文件到 dist 目录中。

既然都要自动生成了,那么 dist 下 index.html 就没必要存在了,删除 dist/index.html,并且新建html模板文件.

新增 public 目录存放公共资源:

- webpack-demo
	- // 其他文件
    - public
		- index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>webpack demo</title>
</head>
<body>
</body>
</html>

安装依赖包

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

配置webpack

// 其他引入
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
   	// 其他配置
    
    plugins: [
        new ExtractTextPlugin("style/style.css"),
        // + 新增配置
        new HtmlWebpackPlugin({
            template: "public/index.html"	// template指定默认html模板
        })
    ]
};

执行打包

npm run build

此时dist/index.html被自动生成,

打开dist/index.html会发现已经自动引入了资源了。

打包前清理旧dist文件夹

使用 clean-webpack-plugin插件 在每次打包前清除下dist文件夹。

注意 中文文档引入方法有坑, 看英文的就ok, 坑是需要解构语法

安装依赖包

npm install --save-dev clean-webpack-plugin 

配置webpack

// 其他代码

// 导入清除插件
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
    // 其他配置

    plugins: [
        new ExtractTextPlugin("style/style.css"),
		
        // 调用清除打包目录插件
        new CleanWebpackPlugin(),
        
        new HtmlWebpackPlugin({
            template: "public/index.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: '想要的文件名.js' // 通常是 bundle.js
  }
};

在这里插入图片描述

日常工作优化

  1. 开发环境
    开发环境一般指的是我们在本地开发时候使用的场景,这种场景下希望代码可以快速追踪错误,不压缩文件,而且由于在本地开发,所以可以加载体积大一点文件, 另外不需要每次都打包, 可以直接观看效果。

错误追踪

我们先来做一个错误追踪的测试,写错一个代码故意

src/index.js

var a = b; //

注意:

  • 上面的代码打包不会报错
  • 浏览器运行会报错,b 没有定义。

执行打包命令

npm run build

刷新dist/index.html网页,在网页中可以看到以下的错误信息。

bundle.js:1 Uncaught ReferenceError: b is not defined
    at e.exports (bundle.js:1)
    at Object.<anonymous> (bundle.js:1)
    at t (bundle.js:1)
    at bundle.js:1
    at bundle.js:1
//上面我们错误的代码,但是浏览器的在报错的时候提示的错误文件是bundle.js,这当然是正常的,因为这是我们
//最后打包出来的文件,但是我们可以通过webpack的source map准确地知道错误来自于哪个源文件。

配置webpack
webpack.config.js

// 其他代码

module.exports = {
    // 其他配置

    devtool: "source-map", // + 生成映射源代码文件

    // 模块加载器配置项
    module: {
        // 其他代码
    },
    
    // 其他配置 

注意: 上面的 devtool:“source-map” 配置会在dist目录中生成一个bundle.js.map文件,该文件主要的作用是把打包后的bundle.js映射到源文件上,这样就可以准确的追踪报错的源代码的位置了。
bundle.js.map文件也会加载到页面中,并且文件体积很大,所以此模式只适用于开发环境。

再次执行打包命名,查看网页检查器console错误提示

error.js:2 Uncaught ReferenceError: b is not defined
    at e.exports (error.js:2)
    at Object.<anonymous> (index.js:7)
    at t (bootstrap:19)
    at bootstrap:83
    at bundle.js:1

此时错误就很精确了,error.js 第3行。

开发服务器

目前我们修改一次代码,就要执行一遍npm run build打包,非常麻烦,webpack 提供了一个简单的开发服务器webpack-dev-server`,该服务器能够帮助我们在本地开启一个开发服务器环境,并且能够监听文件的修改,每当编辑文件保存后浏览器会自动加载刷新页面。

在这里插入图片描述
安装依赖

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

配置webpack
webpack.config.js
配置方法

// 其他代码

module.exports = {
    // 其他配置
    
    devtool: "source-map", 
	
    // + 开发服务配置
    devServer: {
    	contentBase: './dist',
    	port: 8888
  },

    // 模块加载器配置项
    module: {
        // 其他配置
    }
    
    // 其他配置
}

上面的配置devServer可以对开发服务器进行配置,注意:devServer不读取项目中的dist目录,而是读取服务器内存中的文件,我们不需要知道具体的存放地址,只需要知道两者输出的内容是一样的。可以删除项目下的 dist 文件夹进行验证。

下面来添加一个新的scripts命令,用于启动开发服务器。
package.json

{
    // 其他配置
    
	"scripts": {
    	"build": "webpack --config webpack.config.js",
    	"dev": "webpack serve --config ./webpack.config.js --watch"
  	},
    
    // 其他配置
}

–opne没法配置会报错

–watch表示每次保存文件,网页实时更新

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值