webpack4

为了让浏览器能够正确的解析, 我们需要使用 webpack 将我们的源代码进行打包

#1 创建 webpack 配置文件

在根目录下创建 webpack 配置文件 webpack.config.js, 编写最基本的配置

示例

// 使用node的path模块
const path = require('path')

module.exports = {
  // 打包的入口
  entry: './src/main.js',
  // 打包的出口
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
}
  • entry: 指定打包的入口
  • output: 指定打包的出口, 也就是最终生成的文件

演示

#2 编写 webpack 脚本

在 packpage.json 中, 创建一个执行脚本

这样就可以通过npm run build来执行 webpack 打包了

#3 测试

在命令行中执行npm run build

会发现提示这个错误

原因是: webpack 只能打包 js 文件. 对于后缀名为 vue 的文件不能打包. 如何解决呢?

通过 vue-loader 来打包 vue 文件

==============================================

打包vue文件

找到 vue-loader 官网(opens new window)

对于最新的 vue-loader@15 版本, 按照官网的指导, 做如下配置

#1 安装 vue-loader

执行命令, 安装 vue-loader

npm install -D vue-loader vue-template-compiler

安装完成后, 发现 vue-loader 依赖 css-loader, 因此我们也要手动安装一下 css-loader

#2 安装 css-loader

执行npm install -D css-loader

#3 webpack 配置

从 vue-load@15 版本开始, vue-loader 需要在 webpack 中添加一个插件

示例

// 使用node的path模块
const path = require('path')

// 引入vue-loader插件
const VueLoaderPlugin = require('vue-loader/lib/plugin')

module.exports = {
  // 打包的入口
  entry: './src/main.js',
  // 打包的出口
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  // 打包规则
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
      },
    ],
  },
  plugins: [
    // 请确保引入这个插件!
    new VueLoaderPlugin(),
  ],
}

演示

#4 重新打包测试

重新打包, 在 dist 目录下就会生成 bundle.js

解决警告小问题

我们发现在 webpack 打包时会出现这个警告

解决

找到 webpack.config.js 在配置中添加 mode

#5 在主页中引入 bundle.js

在 index.html 中引入 bundle.js 测试, 发现报错

原因

Vue 会打包生成三个文件:

  • runtime only 的文件 vue.common.js
  • compiler only 的文件 compiler.js
  • runtime + compiler 的文件 vue.js

而默认导出的是 vue.common.js, 如何解决呢?

解决

在 webpack 中, 添加别名的配置

resolve: {
    alias: {
      'vue': 'vue/dist/vue.js'
    }
  },

演示

重新打包, 测试

#6 小结

通过上面的练习, 我们知道

  1. webpack 本身只能打包 js 文件, 如果要打包其他文件就需要借助于 loader
  2. loader 其实就是专门用于打包特定文件的处理程序

=====================================

 其他常用loader

一般来说, 一个前端项目除了 js 文件外, 还有一些常用的文件, 如

  • 图片文件
  • css 文件

对于这些文件, webpack 都不会打包, 需要我们安装对应的 loader 帮助 webpack 打包

#1 打包图片文件

#1) file-loader

file-loader: 将文件复制到对应的路径, 并返回文件名

file-loader官方文档(opens new window)

#i 安装 file-loader

执行命令, 安装 file-loader

npm install -D file-loader

演示

#ii 配置

修改 webpack 配置, 添加一条规则

module: {
  rules: [
    {
      test: /\.(jpg|jpeg|png|svg)$/,
      loader: 'file-loader',
    },
  ]
}

  • test: 正则表达式--如果需要打包的文件以 jpg 或者 jpeg 或者 png 或者 svg 结尾时
  • loader: 使用 file-loader

演示

#iii 测试

在 src 目录下创建 assets 目录, 存放静态资源文件(如: images/styles/fonts 等)

在 images 下放一张图片

在 App.vue 中导入图片, 重新打包, 会在 dist 目录下生成我们需要的图片

原理: 当遇到 jpg 结尾的文件时, 使用 file-loader 将文件 copy 到 dist 目录下. 文件名是图片的 hash 值

如果希望保留原有的文件名, 可以使用占位符(placeholder)配置

示例

{
  test: /\.(jpg|jpeg|png|svg)$/,
  loader: 'file-loader',
  options: {
    name: '[name].[ext]'
  }
}

  • [name]: 占位符, 表示使用原文件名
  • [ext]: 占位符, 表示使用原文件扩展名

演示

#2) url-loader

url-loader: 功能类似于 file-loader (opens new window),但是在文件大小(单位 byte)低于指定的限制时,可以返回一个 DataURL。

好处是: 直接将小图片打包以 base64 打包在 js 中, 减少 Http 请求的次数, 提高访问效率

#i 安装 url-loader

执行命令, 安装 url-loader

npm install -D url-loader

提示

由于 url-loader 依赖 file-loader, 因此安装 url-loader 需要先安装 file-loader, 一般来说执行如下命令更适合

npm install -D file-loader url-loader

同时安装 file-loader 和 url-loader

演示

#ii 配置

修改 webpack 配置, 添加一条规则

module: {
  rules: [
    {
      test: /\.(jpg|jpeg|png|svg)$/,
      loader: 'url-loader',
      options: {
        name: '[name].[ext]',
        limit: 2048,
      },
    },
  ]
}

  • test: 正则表达式--如果需要打包的文件以 jpg 或者 jpeg 或者 png 或者 svg 结尾时
  • loader: 使用 url-loader
  • options: 选项
    • limit: 当文件小于 2048K 时, 以 base64 打包到 js 中, 当文件大于 2048K 时, 使用 file-loader 打包
    • name: 打包的文件名使用"源文件名.扩展名"方式

#iii 测试

复制两张小的 svg 图片到 assets 目录下. 并在 App.vue 中导入

运行打包命令npm run build, 在新生成的 bundle.js 中, 可以看到

#2 打包 css 文件

css 文件是前端项目必不可少的文件, webpack 通过 css-loader 和 style-loader 来打包 css 文件

官方文档(opens new window)

#1) 安装

#i 安装 css-loader

在安装 vue-loader 时, 我们已经安装了 css-loader. 可以通过查看package.json确认

#ii 安装 style-loader

在命令行中执行如下命令

npm install -D style-loader

演示

#2) 配置

示例

module: {
  rules: [{
    test: /\.css$/,
    use: ['style-loader', 'css-loader']
  }]
},

  • test: 正则(以 css 结尾的文件)
  • use: 使用两个 loader: style-loader 和 css-loader

注意

这里的书写顺序是有讲究的, 按照从右到左, 从下到上的顺序依次执行

#3) 测试

在 styles 目录下创建 test.css 文件, 编写如下内容

示例

* {
  margin: 0;
  padding: 0;
}

body {
  background-color: red;
}

演示

在 App.vue 中导入 test.css

执行命令npm run build重新打包, 测试, 发现生效

#4) 作用

css-loader: 解决文件之间的依赖关系, 把所有的 css 文件打包成一个文件

style-loader: 将 css-loader 打包完成后生成的文件挂载到页面的 head 标签的 style 中

示例

比如, 在实际项目中一般会把初始化样式独立出来, 再通过 import 引入

css-loader 为分析 css 文件之间的引用关系, 最终形成一个整体文件

再通过 style-loader 将 css-loader 的内容挂载到页面的 head 的 style 标签中

#3 打包 stylus 文件

目前, stylus 做为 node 项目普通使用的 css 预处理器被广泛的应用于 vue 项目中. 大家会发现大部分的 vue 项目中都会使用 stylus 来编写 css.

#1) 推荐的 vscode 插件与配置

  • language-stylus: 提供语法高亮效果和一些支持
  • Supremacy: 自动格式化 stylus 的插件, 可以根据个人习惯或公司的要求, 定制 stylus 格式. 比如是否要;:

这里我对 Supermacy 的配置如下,

不使用{}, 不使用结尾的;, 但是保留:

配置之后, stylus 的样子如下:

#2) 打包 stylus 文件

#i 安装 stylus-loader

执行命令

npm install -D stylus stylus-loader
  • stylus: 是 stylus 文件预处理程序, 作用是将 stylus 编译成 css 格式
  • stylus-loader: 加载 stylus 文件, 调用 stylus 预处理程序形成 css 文件

#ii 配置

示例

module: {
  rules: [{
    test: /\.styl(us)?$/,
    use: ['style-loader', 'css-loader', 'stylus-loader']
  }]
},
  • test: 正则(匹配以 styl 结尾或者 stylus 结尾的文件)
  • use: 依次使用 stylus-loader, css-loader, style-loader 处理

#iii 测试

在 styles 下编写 global.styl 文件, 编写如下内容, 这个也是响应式背景全屏的方案

示例

body
  // 背景图片
  background-image: url('..//http://image.brojie.cn/bg.jpg')
  // 背景图片位置固定
  background-attachment: fixed
  // 背景不要重复
  background-repeat: no-repeat
  // 背景位置居中
  background-position: center center
  // 背景覆盖整个viewport
  background-size: cover
  // 当背景没有加载时的颜色
  background-color: #fff

演示

在 App.vue 中引入 global.styl

示例

import './assets/styles/global.styl'

演示

由于在开发环境, 打包后的文件路径都是相对于 dist 目录, 因此我们还需要暂时把 index.html 移动到 dist 下, 并做如下修改

打包以后测试如下

#3) 处理 vue 文件中的 stylus

在 vue-loader 的官方文档中找到关于 stylus 的配置(opens new window)

#i 安装

在前面, 我们已经安装了 stylus 和 stylus-loader, 这里就不用再安装了

#ii 配置

修改 webpack.config.js

示例

module: {
  rules: [{
    test: /\.styl(us)?$/,
    use: ['vue-style-loader', 'css-loader', 'stylus-loader']
  }]
},
  • vue-style-loader: 是 vue-loader 自带的 style-loader, 在 style-loader 的基础上, 还可以处理 vue 文件中的样式

#iii 测试

我们在 App.vue 中修改一下

打包测试

===============================================

 插件

什么是插件

在某个时间点, 自动执行的处理程序(类似于 vue 的生命周期函数)

#1 使用 html-webpack-plugin 插件

查看该插件的官方文档(opens new window)

#1) 安装

执行命令

npm install -D html-webpack-plugin

#2) 配置

修改 webpack.config.js

#3) 打包测试

在 dist 目录下, 生成了 index.html, 并且自动引入了打包后的 js 文件

这时, 我们直接访问发现只有背景, 没有 App 的内容, 并且报了一个 vue 的错误

我们发现自动生成的 html 中没有 id 为 app 的 div 元素, 如何解决这个问题?

#4) 指定模板

其实, 我们是可以指定生成 html 时, 以哪个文件为模板的

修改 webpack 配置

示例

plugins: [
  new HtmlWebpackPlugin({
    template: './index.html'
  })
],

演示

#5) 小结

html-webpack-plugin 的作用:

在打包结束时, 在 dist 目录下自动生成 index.html 文件, 并把打包好的 js 文件引入到 html 中

#2 使用 clean-webpack-plugin

#1) 安装

执行命令

npm install -D clean-webpack-plugin

1

#2) 配置

webpack 的相关配置

第 10 行: 加{}是 ES6 中的解构的语法, 作用是提取出 CleanWebpackPlugin 的构造函数

#3) 测试

#3 使用 autoprefixer 插件

#1) 安装

autoprefixer 插件是 postcss-loader 提供的一个插件, 如果要使用这个插件, 我们得先安装 postcss-loader

npm install -D postcss-loader autoprefixer

#2) 配置

webpack 配置

新建 postcss.config.js 配置文件

示例

module.exports = {
  plugins: [require('autoprefixer')],
}

演示

#3) 测试

测试发现, 会自动添加厂商前缀

==============================

开发环境

#1 devServer

webpack-dev-server 为你提供了一个简单的 web 服务器,并且能够实时重新加载(live reloading)。

#1) 配置 devServer

查看该部分的相关文档(opens new window)

#i 安装

执行命令

npm install -D webpack-dev-server

#ii 基本配置

示例

webpack 配置

// devServer配置
devServer: {
  // 指定服务器根目录
  contentBase: './dist',
  // 自动打开浏览器
  open: true
},

在 package.json 中添加一个脚本

示例

"scripts": {
  "start": "webpack-dev-server"
},

在命令行中执行npm run start启动 devServer

#2) 测试

测试发现, 只要代码修改后, webpack 会自动重新打包, 页面会重新刷新加载. 这样就不需要每次执行打包命令了

#3) 其他常见配置

查看该部分的相关文档(opens new window)

  • host: 服务器主机
  • port: 端口
  • open: 打开浏览器
  • hot: 热模块替换
  • proxy: 代理

#2 热模块替换

查看该部分的相关文档(opens new window)

#1) 启用

#i 配置

示例

devServer: {
  // 指定服务器根目录
  contentBase: './dist',
  // 自动打开浏览器
  open: true,
  // 启用热模块替换
  hot: true
},

#ii 插件

#2) 测试

编写业务代码 App.vue

示例

<template>
  <div>
    <h1>TodoList</h1>
    <input type="text" v-model="content" />
    <button @click="addTodo">添加</button>
    <ul>
      <li v-for="item of todoData" :key="item.id">{{ item }}</li>
    </ul>
  </div>
</template>

<script>
import './assets/styles/global.styl'

export default {
  name: 'App',
  data() {
    return {
      todoData: ['todo1', 'todo2', 'todo3'],
      content: '',
    }
  },
  methods: {
    addTodo() {
      if (this.content === '') return

      this.todoData.push(this.content)
      this.content = ''
    },
  },
}
</script>

<style lang="stylus" scoped>
li:nth-of-type(odd)
  color: red
</style>

修改颜色, 发现之前添加的内容依然存在

#3 SourceMap

SourceMap: (源代码映射) 建立打包后的文件和源代码所在行的映射,

主要作用: 在开发时快速定位到出错的源代码行

查看该部分的相关文档(opens new window)

以及相关文档(opens new window)

===============

生产环境

开发环境(development) 和 生产环境(production) 的构建目标差异很大。

  • 在 开发环境 中,我们需要具有强大的、具有实时重新加载(live reloading)或热模块替换(hot module replacement)能力的 source map 和 localhost server。
  • 在 生产环境 中,我们的目标则转向于关注更小的 bundle,更轻量的 source map,以及更优化的资源,以改善加载时间

因此, 配置会有所不同, 官方推荐使用两个不同的配置文件

  • webpack.dev.js: 用于开发环境
  • webpack.prod.js: 用于生产环境

#1 分别指定两个配置文件

示例

webpack.dev.js

// 使用node的path模块
const path = require('path')
// 引入vue-loader插件
const VueLoaderPlugin = require('vue-loader/lib/plugin')

// 导入html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin')

// 导入clean-webpack-plugin
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

// 导入webpack
const webpack = require('webpack')

module.exports = {
  // 模式
  mode: 'development',
  devtool: 'cheap-module-eval-source-map',
  // 打包的入口
  entry: './src/main.js',
  // devServer配置
  devServer: {
    // 指定服务器根目录
    contentBase: './dist',
    // 自动打开浏览器
    open: true,
    // 启用热模块替换
    hot: true,
  },
  // 插件
  plugins: [
    // 请确保引入这个插件!
    new VueLoaderPlugin(),
    new HtmlWebpackPlugin({
      template: './index.html',
    }),
    new CleanWebpackPlugin(),
    new webpack.HotModuleReplacementPlugin(),
  ],

  // 打包的出口
  output: {
    filename: 'app.js',
    path: path.resolve(__dirname, 'dist'),
  },
  // 打包规则
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
      },
      {
        test: /\.(jpg|jpeg|png|svg)$/,
        loader: 'url-loader',
        options: {
          name: '[name].[ext]',
          limit: 2048,
        },
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader'],
      },
      {
        test: /\.styl(us)?$/,
        use: ['style-loader', 'css-loader', 'postcss-loader', 'stylus-loader'],
      },
    ],
  },
  resolve: {
    alias: {
      vue: 'vue/dist/vue.js',
    },
  },
}

webpack.prod.js

// 使用node的path模块
const path = require('path')
// 引入vue-loader插件
const VueLoaderPlugin = require('vue-loader/lib/plugin')

// 导入html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin')

// 导入clean-webpack-plugin
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = {
  // 模式
  mode: 'production',
  // 打包的入口
  entry: './src/main.js',
  // 插件
  plugins: [
    // 请确保引入这个插件!
    new VueLoaderPlugin(),
    new HtmlWebpackPlugin({
      template: './index.html',
    }),
    new CleanWebpackPlugin(),
  ],

  // 打包的出口
  output: {
    filename: 'app.js',
    path: path.resolve(__dirname, 'dist'),
  },
  // 打包规则
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
      },
      {
        test: /\.(jpg|jpeg|png|svg)$/,
        loader: 'url-loader',
        options: {
          name: '[name].[ext]',
          limit: 2048,
        },
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader'],
      },
      {
        test: /\.styl(us)?$/,
        use: ['style-loader', 'css-loader', 'postcss-loader', 'stylus-loader'],
      },
    ],
  },
  resolve: {
    alias: {
      vue: 'vue/dist/vue.js',
    },
  },
}

修改 package.json

"scripts": {
  "dev": "webpack-dev-server --config ./webpack.dev.js",
  "build": "webpack --config ./webpack.prod.js"
},

#2 提取公共部分

使用 webpack-merge 工具

#1) 安装 webpack-merge

执行命令

npm install -D webpack-merge

#2) 创建 build 目录

创建 3 个文件

  • webpack.base.js: 公共配置
  • webpack.dev.js: 开发环境配置
  • webpack.prod.js: 生产环境配置

示例

webpack.base.js

// 使用node的path模块
const path = require('path')
// 引入vue-loader插件
const VueLoaderPlugin = require('vue-loader/lib/plugin')

// 导入html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin')

// 导入clean-webpack-plugin
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = {
  // 打包的入口
  entry: './src/main.js',

  // 插件
  plugins: [
    // 请确保引入这个插件!
    new VueLoaderPlugin(),
    new HtmlWebpackPlugin({
      template: './index.html',
    }),
    new CleanWebpackPlugin(),
  ],

  // 打包的出口
  output: {
    filename: 'app.js',
    path: path.resolve(__dirname, '..', '/dist'),
  },
  // 打包规则
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
      },
      {
        test: /\.(jpg|jpeg|png|svg)$/,
        loader: 'url-loader',
        options: {
          name: '[name].[ext]',
          limit: 2048,
        },
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader'],
      },
      {
        test: /\.styl(us)?$/,
        use: ['style-loader', 'css-loader', 'postcss-loader', 'stylus-loader'],
      },
    ],
  },
  resolve: {
    alias: {
      vue: 'vue/dist/vue.js',
    },
  },
}

webpack.dev.js

// 导入webpack
const webpack = require('webpack')

const merge = require('webpack-merge')
const baseConfig = require('./webpack.base.js')

const devConfig = {
  // 模式
  mode: 'development',
  devtool: 'cheap-module-eval-source-map',
  devServer: {
    // 指定服务器根目录
    contentBase: './dist',
    // 自动打开浏览器
    open: true,
    // 启用热模块替换
    hot: true,
  },
  // 插件
  plugins: [new webpack.HotModuleReplacementPlugin()],
}

module.exports = merge(baseConfig, devConfig)

webpack.prod.js

const merge = require('webpack-merge')
const baseConfig = require('./webpack.base.js')

const prodConfig = {
  // 模式
  mode: 'production',
}

module.exports = merge(baseConfig, prodConfig)

#3) 改写 package 配置

示例

"scripts": {
  "dev": "webpack-dev-server --config ./build/webpack.dev.js",
  "build": "webpack --config ./build/webpack.prod.js"
},

视频:使用webpack+vue从零开始打造前端项目(2020最新版)_哔哩哔哩_bilibili

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值