1. 搭建 webpack 基本环境

1.1 初始化项目

在命令行中执行 npm init 然后一路回车就行了,主要是生成一些项目基本信息。最后会生成一个 package.json 文件


npm init

1.2 安装 webpack


npm install webpack webpack-cli -D

1.3 测试一下webpack是否安装成功了

新建一个src文件夹,然后再建一个main.js文件


// src/main.js
console.log('hello webpack')

然后在 package.json 下面加一个脚本命令


"script":{
  "serve": "webpack ./src/main.js --mode development"
}

然后运行该命令


npm run serve

如果在 dist 目录下生成了一个main.js文件,则表示webpack工作正常

2. 开始配置功能

  • 新建一个 build 文件夹,用来存放 webpack配置相关的文件
  • 在build文件夹下新建一个webpack.config.js,配置webpack的基本配置
  • 修改 webpack.config.js配置

module.exports = {
    //指定打包模式
    mode: 'development',
    entry: {
        //配置入口文件
        main: path.resolve(__dirname, '../src/main.js')
    },
    output: {
        //配置打包文件的输出目录
        path: path.resolve(__dirname, '../dist'),
        //生成的js文件名称
        filename: 'js/[name].[hash:8].js',
        //申城的chunk名称
        chunkFilename: 'js/[name].[hash:8].js',
        // 资源引用路劲
        publicPath: './'
    },
}
  • 修改package.json 文件,将之前添加的 serve 修改为

"serve": "webpack ./src/main.js --config ./build/webpack.config.js"

2.1 配置 ES6/7/8 转 ES5代码

  • 安装相关依赖

npm install babel-loader @babel/core @babel/preset-env

  • 修改webpack.config.js配置

const path = require('path')

module.exports = {
    //指定打包模式
    mode: 'development',
    entry: {
        //配置入口文件
        main: ["@babel/polyfill", path.resolve(__dirname, '../src/main.js')]
    },
    output: {
        //配置打包文件的输出目录
        path: path.resolve(__dirname, '../dist'),
        //生成的js文件名称
        filename: 'js/[name].[hash:8].js',
        //申城的chunk名称
        chunkFilename: 'js/[name].[hash:8].js',
        // 资源引用路劲
        publicPath: './'
    },
    module: {
        rules: [
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                use: [
                    {
                        loader: 'cache-loader'
                    },
                    {
                        loader: 'thread-loader'
                    },
                    {
                        loader: 'babel-loader'
                    }
                ]
            },
        ]
    },

}
  • 在项目根目录添加一个 babel.config.js 文件

module.exports = {
    presets: [
        "@babel/preset-env"
    ]
}

2.1.1 ES6/7/8 Api 转es5

babel-loader只会将 ES6/7/8语法转换为ES5语法,但是对新api并不会转换。

我们可以通过 babel-polyfill 对一些不支持新语法的客户端提供新语法的实现

  • 安装

npm install @babel/polyfill

  • 修改webpack.config.js配置

在 entry 中添加 @babel-polyfill


entry: {
        //配置入口文件
        main: ["@babel/polyfill", path.resolve(__dirname, '../src/main.js')]
    },

2.2 配置 scss 转 css

在没配置 css 相关的 loader 时,引入scss、css相关文件打包的话,会报错

  • 安装相关依赖

npm install sass-loader dart-sass css-loader style-loader -D

sass-loader, dart-sass主要是将 scss/sass 语法转为css

css-loader主要是解析 css 文件

style-loader 主要是将 css 解析到 html页面 的 style 上

  • 修改webpack.config.js配置

module: {
        rules: [
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                use: [
                    {
                        loader: 'cache-loader'
                    },
                    {
                        loader: 'thread-loader'
                    },
                    {
                        loader: 'babel-loader'
                    }
                ]
            },
            {
                test: /\.(scss|sass)$/,
                use: [
                    {
                        loader: 'style-loader'
                    },
                    {
                        loader: 'css-loader',
                    },
                    {
                        loader: 'sass-loader',
                        options: {
                            implementation: require('dart-sass')
                        }
                    },
                ]
            },
        ]
    },

2.3 配置 postcss 实现自动添加css3前缀

  • 安装相关依赖

npm install postcss-loader autoprefixer -D

  • 修改webpack.config.js配置

module: {
        rules: [
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                use: [
                    {
                        loader: 'cache-loader'
                    },
                    {
                        loader: 'thread-loader'
                    },
                    {
                        loader: 'babel-loader'
                    }
                ]
            },
            {
                test: /\.(scss|sass)$/,
                use: [
                    {
                        loader: 'style-loader'
                    },
                    {
                        loader: 'css-loader',
                        options: {
                            importLoaders: 2
                        }
                    },
                    {
                        loader: 'sass-loader',
                        options: {
                            implementation: require('dart-sass')
                        }
                    },
                    {
                        loader: 'postcss-loader'
                    }
                ]
            },
        ]
    },
  • 在项目根目录下新建一个 postcss.config.js

module.exports = {
    plugins: {
        autoprefixer: {}
    }
}

2.3 使用 html-webpack-plugin来创建html页面

使用 html-webpack-plugin来创建html页面,并自动引入打包生成的js文件

  • 安装依赖

npm install html-webpack-plugin -D

  • 新建一个 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>Document</title>
</head>
<body>
  <div id="app"></div>
</body>
</html>

  • 修改 webpack-config.js 配置

const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    plugins: [
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, '../public/index.html')
        }),
        new webpack.NamedModulesPlugin(),
        new webpack.HotModuleReplacementPlugin(),
        new VueLoaderPlugin()
    ]
}

2.4 配置 devServer 热更新功能

通过代码的热更新功能,我们可以实现不刷新页面的情况下,更新我们的页面

  • 安装依赖

npm install webpack-dev-server -D

  • 修改webpack.config.js配置

通过配置 devServer 和 HotModuleReplacementPlugin 插件来实现热更新


module.exports = {
    devServer: {
        hot: true,
        port: 3000,
        contentBase: './dist'
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, '../public/index.html')
        }),
        new webpack.NamedModulesPlugin(),
        new webpack.HotModuleReplacementPlugin(),
        new VueLoaderPlugin()
    ]
}

2.5 配置 webpack 打包 图片、媒体、字体等文件

  • 安装依赖

npm install file-loader url-loader -D

file-loader 解析文件url,并将文件复制到输出的目录中

url-loader 功能与 file-loader 类似,如果文件小于限制的大小。则会返回 base64 编码,否则使用 file-loader 将文件复制到输出的目录中

  • 修改 webpack-config.js 配置 添加 rules 配置,分别对 图片,媒体,字体文件进行配置

// build/webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')
module.exports = {
  // 省略其它配置 ...
  module: {
    rules: [
      // ...
      {
        test: /\.(jpe?g|png|gif)$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 4096,
              fallback: {
                loader: 'file-loader',
                options: {
                    name: 'img/[name].[hash:8].[ext]'
                }
              }
            }
          }
        ]
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 4096,
              fallback: {
                loader: 'file-loader',
                options: {
                  name: 'media/[name].[hash:8].[ext]'
                }
              }
            }
          }
        ]
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 4096,
              fallback: {
                loader: 'file-loader',
                options: {
                  name: 'fonts/[name].[hash:8].[ext]'
                }
              }
            }
          }
        ]
      },
    ]
  },
  plugins: [
    // ...
  ]
}

让 webpack 识别 .vue 文件

  • 安装需要的依赖文件

npm install vue-loader vue-template-compiler cache-loader thread-loader -D
npm install vue -S

vue-loader 用于解析.vue文件
vue-template-compiler 用于编译模板
cache-loader 用于缓存loader编译的结果
thread-loader 使用 worker 池来运行loader,每个 worker 都是一个 node.js 进程。

  • 修改 webpack.config.js配置

// build/webpack.config.js
const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
  // 指定打包模式
  mode: 'development',
  entry: {
    // ...
  },
  output: {
    // ...
  },
  devServer: {
    // ...
  },
  resolve: {
    alias: {
      vue$: 'vue/dist/vue.runtime.esm.js'
    },
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        use: [
          {
            loader: 'cache-loader'
          },
          {
            loader: 'thread-loader'
          },
          {
            loader: 'vue-loader',
            options: {
              compilerOptions: {
                preserveWhitespace: false
              },
            }
          }
        ]
      },
      {
        test: /\.jsx?$/,
        use: [
          {
            loader: 'cache-loader'
          },
          {
            loader: 'thread-loader'
          },
          {
            loader: 'babel-loader'
          }
        ]
      },
      // ...
    ]
  },
  plugins: [
    // ...
    new VueLoaderPlugin()
  ]
}

  • 测试一下
  1. 在 src 新建一个 App.vue

// src/App.vue
<template>
  <div class="App">
    Hello World
  </div>
</template>

<script>
export default {
  name: 'App',

  data() {
    return {};
  }
};
</script>

<style lang="scss" scoped>
.App {
  color: skyblue;
}
</style>

  1. 修改 main.js

import Vue from 'vue'
import App from './App.vue'

new Vue({
  render: h => h(App)
}).$mount('#app')

  1. 运行一下
plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        VUE_APP_BASE_URL: JSON.stringify('http://localhost:3000')
      }
    }),
]


笨蛋、笨蛋!