Vue.js 之 webpack学习(八)

nrm 的安装和使用

作用:提供一些常用 NPM 包镜像地址,包括国内的:cnpm、淘宝镜像,可以加快 npm 包下载速度(npm 镜像默认从国外官网下载,速度很慢)

安装:

  • 安装:npm i nrm -g 全局安装 nrm
  • 查看:nrm ls 查看当前可以镜像源地址
  • 切换:nrm use npmnrm use taobao 切换不同的镜像源地址

使用演示:

# 查看所有能用的镜像源地址
$ D:\软件\100-编码相关\cmder>nrm ls

* npm -------- https://registry.npmjs.org/
  yarn ------- https://registry.yarnpkg.com/
  cnpm ------- http://r.cnpmjs.org/
  taobao ----- https://registry.npm.taobao.org/
  nj --------- https://registry.nodejitsu.com/
  npmMirror -- https://skimdb.npmjs.com/registry/
  edunpm ----- http://registry.enpmjs.org/

# 切换到淘宝镜像源地址
$ D:\软件\100-编码相关\cmder>nrm use taobao


   Registry has been set to: https://registry.npm.taobao.org/

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

  • JS:.js .jsx .coffee .ts(TypeScript 类 C# 语言)
  • CSS:.css .less .sass .scss
  • Images:.jpg .png .gif .bmp .svg
  • 字体文件(Fonts):.svg .ttf .eot .woff .woff2
  • 模板文件:.ejs .jade .vue

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

  1. 网页加载速度慢, 导致要发起很多的二次请求
  2. 要处理错综复杂的依赖关系

如何解决上述两个问题

  1. 合并、压缩、精灵图、图片的 Base64 编码
  2. requireJSwebpack 解决各个包之间的依赖关系

什么是webpack

webpack 是前端的一个项目构建工具,它是基于 Node.js 开发出来的一个前端工具;它可以实现资源的合并、打包、压缩和混淆等功能,也能解决各个包之间的依赖关系,比如低版本浏览器不能识别 ES6 语法,通过 webpack 转换成浏览器识别的语法。

webpack 官网

webpack 安装

两种方式:

  • 全局安装:npm i webpack -g,全局都可以使用 webpack 命令,不推荐全局安装
  • 局部安装(项目):npm i webpack --save-dev 安装到项目依赖中
  • 其他安装:npm install webpack-cli --save-dev

初步使用

使用 webpack 打包构建列表隔行变色案例:

1、运行 npm init 初始化项目,使用 npm 管理项目中的依赖包,会生成一个 package.json 文件
2、创建项目基本结构:srcdist(发布)
3、安装 webpack、webpack、jQuery

  • npm i webpack --save-dev
  • npm i webpack-cli --save-dev
  • npm i jquery --save-dev
    4、创建 index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>初次使用 webpack </title>
    <!-- <script src="./main.js"></script> -->
    <script src="../dist/bundle.js"></script>

    <!-- Uncaught SyntaxError: Cannot use import statement outside a module -->
</head>
<body>
    <ul id="list">
        <li>123</li>
        <li>123</li>
        <li>123</li>
        <li>123</li>
        <li>123</li>
        <li>123</li>
        <li>123</li>
        <li>123</li>
        <li>123</li>
        <li>123</li>
        <li>123</li>
    </ul>
</body>
</html>

5、创建 main.js 入口文件:

// 入口 js 文件
// 导入 jQuery 类,导入 jQuery 并取名为 $
import $ from 'jquery'      // ES6 才新增的语法,低版本浏览器不能识别,需要使用 webpack 转换

$(function () {
    // 设置偶数行背景色,索引从 0 开始,0 为偶数
    $('li:even').css('backgroundColor', 'lightblue');

    // 设置奇数行背景色
    $('li:odd').css('backgroundColor', function () {
        return '#' + 'D97634'
    });
})

importES6 才新增的语法,低版本浏览器不能识别,需要使用 webpack 转换:

6、运行 webpack 入口文件路径 输出文件路径main.js 进行处理,将 main.js 转换到 dist/bundle.js 文件中,使得低版本浏览器能够支持 import 语法:

// webpack 4.x 版本
// 使用 webpack3.x 命名会报错:Module not found: Error: Can't resolve 'dist/bundle.js'
webpack .\src\main.js -o .\dist\bundle.js --mode=development

// webpack 3.x 版本
webpack .\src\main.js .\dist\bundle.js

踩坑记录

1、运行:webpack .\src\main.js -o .\dist\bundle.js --mode=development时,报错:webpack : 无法加载文件 C:\Users\dly15\AppData\Roaming\npm\webpack.ps1,因为在此系统上禁止运行脚本。

解决:若要在本地计算机上运行您编写的未签名脚本和来自其他用户的签名脚本,请使用以下命令将计算机上的 执行策略更改为 RemoteSigned

  • Windows 管理员模式打开 PowerShell,执行:set-ExecutionPolicy RemoteSigned,输入 y,回车
  • get-ExecutionPolicy 命令查看执行策略是否为: RemoteSigned

2、全局安装了 webpackwebpack-cli,打包时报:We will use "npm" to install the CLI via "npm install -D". Which one do you like to install (webpack-cli/webpack-command):

解决:不用全局安装,项目中安装 webpackwebpack-cli

注意:修改文 package.json 后要重启:npm run dev

使用 webpack 配置文件简化打包命令

在上面我们使用 webpack .\src\main.js -o .\dist\bundle.js --mode=development 命令来打包文件,使得浏览器能够识别。但是当我们需要经常改动 main.js,并能够实时查看页面变化时,这种方式就显得太繁琐了,这时就需要用到 webpack 的配置文件来简化打包命令。

1、在项目根目录创建 webpack 配置文件:webpack.config.js

2、指定运行 webpack 命令时的入口文件和输出文件路径:

var path = require('path')

module.exports = {
    entry: path.join(__dirname, './src/main.js'), //入口文件
    output: {
        // 输出选项
        path: path.join(__dirname, './dist'),   // 输出路径
        filename: 'bundle.js',  // 指定输出文件名称
    },
}

项目目录结构

dist
    - bundle.js
node_modules
src
    - css
    - images
    - js
    - index.html    
    - main.js
package.json
webpack.config.js   // webpack 配置文件

配置完毕后,就可以使用 webpack 命令来打包。

webpack-dev-server 实现实时打包

每次重新修改代码后,都需要手动运行 webpack 命令,比较麻烦,可以不使用 webpack-dev-server 插件来实现代码实时打包编译,
当修改代码后,它会自动进行打包构建。

1、安装到项目依赖:

npm i webpack-dev-server --save-dev

2、借助 package.jsonScripts 节点来指定打包指令:

{
  "name": "day05",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server --open --port 3000 --hot"       // 新增
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "jquery": "^3.4.1",
    "webpack-dev-server": "^3.10.3"
  },
  "devDependencies": {
    "webpack": "^4.41.6",
    "webpack-cli": "^3.3.11"
  }
}

webpack-dev-server 会将打包编译的 bundle.js 文件放在 内存,而不是 dist/ 目录下,这也是它为什么能
快速打包编译的原因。

3、运行 npm run dev 命令,直接打开浏览器跳转到 http://localhost:3000 (默认 8080) 访问到首页。也可以使用 --contentBase src
参数来指定启动目录:

"dev": "webpack-dev-server --contentBase src"

4、修改 index.html 中的 bundle.js 引入路径:

// 此刻的 bundle.js 不在 dist 目录中,而是在内存中,这里使用的是相对路径
<script src="/bundle.js"></script>

// 原先
<script src="../dist/bundle.js"></script>

至此所有的配置都已完成,当我们修改 main.js 文件时,webpack-dev-server 就会自动帮我们实时打包编译,不需要再手动执行打包编译命令。

注意:修改 package.js 后需要重启,命令:npm run dev

webpack-dev-server 两种配置方式

  • package.json"dev2": "webpack-dev-server --open --port 3000 --hot --contentBase src",
  • webpack.config.js:配置参数,package.json 中配置命令

1、package.json

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    // "dev2": "webpack-dev-server --open --port 3000 --hot --contentBase src",
    "dev": "webpack-dev-server" // 命令
  },

2、webpack.config.js

var path = require('path')

// 启用热更新第 2 步
const webpack = require('webpack')

module.exports = {
    entry: path.join(__dirname, './src/main.js'), //入口文件
    output: {
        // 输出选项
        path: path.join(__dirname, './dist'),   // 输出路径
        filename: 'bundle.js',  // 指定输出文件名称
    },
    devServer: {
        // 配置 webpack-dev-server 的第二种方式
        open: true, // 自动打开浏览器
        port: 3000,
        contentBase: 'src', // 指定托管的根目录
        hot: true   // 启用热更新第 1 步
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin()    // new 一个热更新的模块对象,启动热更新
    ]
}

注意:此种方式不推荐使用!

html-webpack-plugin 插件配置启动页面

由于使用 --contentBase 指令过于繁琐,需要指定启动的目录,还需要修改 index.htmlscript 标签的 src 熟悉,推荐使用 htm-webpack-plugin 来启动页面。

作用:

  • 自动在内存中根据指定页面生成一个内存的页面
  • 自动把打包好的 bundle.js 追加到页面中去

在内存中生成 HTML 页面

当使用 html-webpack-plugin 之后,就不再需要手动处理 bundle.js 的引用路径了,它会帮我们自动创建一个合适的 script,并引用正确的路径。

1、安装:npm i html-webpack-plugin --save-dev

2、修改 webpack.config.js配置文件如下:

var path = require('path')

// 启用热更新第 2 步
const webpack = require('webpack');

// 导入:html-webpack-plugins
var htmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: path.join(__dirname, './src/main.js'), //入口文件
    output: {
        // 输出选项
        path: path.join(__dirname, './dist'),   // 输出路径
        filename: 'bundle.js',  // 指定输出文件名称
    },
    devServer: {
        // 配置 webpack-dev-server 的第二种方式
        open: true, // 自动打开浏览器
        port: 3000,
        contentBase: 'src', // 指定托管的根目录
        hot: true   // 启用热更新第 1 步
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin(),    // new 一个热更新的模块对象,启动热更新
        // 所有 webpack 插件的配置节点
        new htmlWebpackPlugin({
            template: path.join(__dirname, './src/index.html'), // 指定模板文件路径
            filename: 'index.html' // 设置生成内存页面的名称
        })
    ]
}

先导入 html-webpack-plugins 插件,再在 plugins 数组中配置相应模板文件路径和名称。

3、修改package.jsonscript节点中的dev指令如下:

"dev": "webpack-dev-server"

4、可以将 index.html 中的 script 注释掉,因为 html-webpack-plugins 会自动引用,查看网页源代码:

webpack 打包 css、less 和 sass 文件

使用 link 标签引用 css、less、sass 等文件时会发送二次请求,可以在 main.js 中 import

webpack 默认只能打包处理 js 文件,无法处理其他类型文件,若想处理其他类型文件需要安装第三方 loader

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

  • 发现要处理的文件是非 js 文件,就去配置文件中查找有没有对应的第三方 loader 规则
  • 若有 loader 规则,则调用,否则编译失败
  • 调用顺序,从后往前
  • 当最后一个 loader 调用完毕后,会将处理结果交给 webpack 进行打包合并,并最终输出到 bundle.js

打包 css 文件

1、新建 css/index.css

li {
    list-style: none;
}

2、在 main.js 中进行引用:

// 入口 js 文件
// 导入 jQuery 类,导入 jQuery 并取名为 $
import $ from 'jquery'

import './css/index.css'	// 引用 css 文件

$(function () {
    // 设置偶数行背景色,索引从 0 开始,0 为偶数
    $('li:even').css('backgroundColor', 'yellow');

    // 设置奇数行背景色
    $('li:odd').css('backgroundColor', function () {
        return '#' + 'D97634'
    });
})

3、安装 cnpm i style-loader css-loader --save-dev

4、修改 webpack.config.js

module.exports = {
    plugins: [
        new webpack.HotModuleReplacementPlugin(),    // new 一个热更新的模块对象,启动热更新
        // 所有 webpack 插件的配置节点
        new htmlWebpackPlugin({
            template: path.join(__dirname, './src/index.html'), // 指定模板文件路径
            filename: 'index.html' // 设置生成内存页面的名称
        })
    ],

    // 配置第三方模块加载器 loader
    module: {
        rules: [
            // test: 正则匹配,点需要转义,这里是匹配以 .css 结尾的文件
            { test: /\.css$/, use: ['style-loader', 'css-loader'] },
        ]
    }
}

打包 less 文件

1、新建 css/index.less

ul {
    padding: 0;
    margin: 0;
}

2、在 main.js 中进行引用:

// 入口 js 文件
// 导入 jQuery 类,导入 jQuery 并取名为 $
import $ from 'jquery'

import './css/index.css'	// 引用 css 文件
import './css/index.less'	// 引用 less 文件

$(function () {
    // 设置偶数行背景色,索引从 0 开始,0 为偶数
    $('li:even').css('backgroundColor', 'yellow');

    // 设置奇数行背景色
    $('li:odd').css('backgroundColor', function () {
        return '#' + 'D97634'
    });
})

3、安装 cnpm i less-loader less -D

4、修改 webpack.config.js

module.exports = {
    plugins: [
        new webpack.HotModuleReplacementPlugin(),    // new 一个热更新的模块对象,启动热更新
        // 所有 webpack 插件的配置节点
        new htmlWebpackPlugin({
            template: path.join(__dirname, './src/index.html'), // 指定模板文件路径
            filename: 'index.html' // 设置生成内存页面的名称
        })
    ],

    // 配置第三方模块加载器 loader
    module: {
        rules: [
            // test: 正则匹配,点需要转义,这里是匹配以 .css 结尾的文件
            { test: /\.css$/, use: ['style-loader', 'css-loader'] },
            { test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] },
        ]
    }
}

打包 sass 文件

1、新建 css/index.scss

html, body{
  margin: 0;
  padding: 0;

  li{
    font-size: 12px;
    line-height: 30px;
  }
}

2、在 main.js 中进行引用:

// 入口 js 文件
// 导入 jQuery 类,导入 jQuery 并取名为 $
import $ from 'jquery'

import './css/index.css'	// 引用 css 文件
import './css/index.less'	// 引用 less 文件
import './css/index.scss'	// 引用 scss 文件

$(function () {
    // 设置偶数行背景色,索引从 0 开始,0 为偶数
    $('li:even').css('backgroundColor', 'yellow');

    // 设置奇数行背景色
    $('li:odd').css('backgroundColor', function () {
        return '#' + 'D97634'
    });
})

3、安装 cnpm i sass-loader node-sass --save-dev

4、修改 webpack.config.js

module.exports = {
    plugins: [
        new webpack.HotModuleReplacementPlugin(),    // new 一个热更新的模块对象,启动热更新
        // 所有 webpack 插件的配置节点
        new htmlWebpackPlugin({
            template: path.join(__dirname, './src/index.html'), // 指定模板文件路径
            filename: 'index.html' // 设置生成内存页面的名称
        })
    ],

    // 配置第三方模块加载器 loader
    module: {
        rules: [
            // test: 正则匹配,点需要转义,这里是匹配以 .css 结尾的文件
            { 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'] },
        ]
    }
}

处理 CSS 中 URL 地址

webpack 无法处理 css 文件中的 URL 地址,不管是图片还是字体库,都不能处理,需要采用第三方 loaderurl-loader、file-loader

1、新增 index.html

<div class="box">
    
</div>

2、修改 css/index.scss

html, body{
    margin: 0;
    padding: 0;
  
    li{
      font-size: 12px;
      line-height: 30px;
    }

    .box {
        width: 220px;
        height: 120px;
        background: url('../images/生小孩.jpg');
        background-size: cover;
    }
  }

3、安装:cnpm i url-loader file-loader --save-dev

4、webpack.config.js

// 配置第三方模块加载器 loader
module: {
    rules: [
        // test: 正则匹配,点需要转义,这里是匹配以 .css 结尾的文件
        { 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'] },

        // 处理 css 中 url 地址
        { test: /\.(jpg|png|gif|bmp|jpeg)$/, use: 'url-loader?limit=7630' }    
    ]
}

参数

webpack 处理图片,图片地址默认为 base64,若不想以 base64 显示,可以配置相应参数:

  • limit: 给定的值为图片的字节大小(byte),若大于图片大小,则会转换为 base64,小于或等于则不会(哈希值)
  • name:若想使用图片原有名称,可以使用 name 参数,用法:{ test: /\.(jpg|png|gif|bmp|jpeg)$/, use: 'url-loader?limit=7630&name=[name].[ext]' } ,其中 .[ext] 为固定写法

当有两张名称相同,但所属不同目录的图片,分别被 HTML 引用时,且都使用的图片原名称;webpack 打包后,页面只会显示其中一张图片。

解决办法:

// 在 [name] 之前添加一个 [hash:8]-,表示将图片名称进行哈希,并只取前 8 位
{ test: /\.(jpg|png|gif|bmp|jpeg)$/, use: 'url-loader?limit=7631&name=[hash:8]-[name].[ext]' }, 

处理 ttf、svg 等字体文件

也是使用 url-loader 处理字体文件,以下以 Bootstrap 样式中的字体文件为例:

1、index.html

<span class="glyphicon glyphicon-heart" aria-hidden="true"></span>

2、安装 cnpm i bootstrap -S

3、引入 Bootstrapmain.js

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

安装的第三方包在 node_modules/ 文件夹中,引入时可省略 node_modules 前缀

4、webpack.config.js

// 配置第三方模块加载器 loader
module: {
    rules: [
        // 处理字体文件
        { test: /\.(ttf|eot|svg|woff|woff2)$/, use: 'url-loader' },   
    ]
}

使用 babel 处理高级 JS 语法

webpack 默认只能处理一部分 ES6 的新语法,一些更高级的或者 ES7 语法无法处理;需要借助第三方 loader 来处理,它们可以将高级语法转换为低级语法,把结果交给 webpack 去打包。

1、main.js 中新增:

class Person {
    // 静态方法
    static info = { name: 'zs', age: 18 }
}

console.log(Person.info)

class PersonES6 中的语法,webpack 处理不了,需要借助:babel-loader 来处理。

2、安装:

cnpm i babel-core babel-loader babel-plugin-transform-runtime -D
cnpm i babel-preset-env babel-preset-stage-0 -D

// 为保证运行不会出错,babel 各个版本与示例中尽量保持一致,高版本可能不会生效
cnpm i babel-core@6.26.0 babel-loader@7.1.2 babel-plugin-transform-runtime@6.23.0 -D
cnpm i babel-preset-env@1.6.1 babel-preset-stage-0@6.24.1 -D

3、webpack.config.js 新增 rules 匹配规则:

{ test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ },	// exclude:排除 node_modules 目录中的 js 文件

注意:babel-loader 会将高级 JS 语法转换为低级 JS 语法,涉及到的文件只有 main.js,不包括 node_module/ 中的 JS,因此需要将其排除掉,否则也会将 node_modules/ 中的 JS 文件打包编译,会消耗CPU,同时打包速度会非常慢。

4、项目根目录新建:.babelrc 文件:

{
  "presets": ["env", "stage-0"],
  "plugins": ["transform-runtime"]
}

注意:该文件为 json 格式文件,必须符合 json 格式语法

参考文章

posted @ 2020-09-03 22:46  Hubery_Jun  阅读(284)  评论(0编辑  收藏  举报