webpack入门配置---搭建基础Vue环境

932 阅读5分钟

1.概述

如果你打开了这篇文章,那么希望你可以和我一起探究webpack。首先,webpack有什么用?平时开发项目时,不管你是使用Vue还是React,脚手架都帮我们搭建好了整个项目。其实脚手架都是依赖于webpack,webPack的主要作用就是将浏览器不能识别的ts文件、ES6语法、less、sass等各种文件进行打包编译,转换成浏览器可以识别的静态资源。下面我们将学习如何在不依赖脚手架的情况下,利用webpack将各种资源进行打包。

必备官方网站:webpack.docschina.org/configurati…

2.准备工作

2.1 需要编译的文件

开始工作前,我们得知道,有哪些文件是需要进行编译的?

  • JavaScript文件: 将ES6转换成ES5的语法; TypeScript转换成JavaScript;
  • Css的处理: CSS文件模块的加载和提取; Less、Sass等预处理器的处理;
  • 资源文件处理: 图片img文件的加载;字体font文件的加载等;
  • HTML文件的处理;
  • .Vue文件处理;
  • ......

2.2 安装资源

首先当然需要Node环境,学到webpack的朋友肯定都有了,另外还需全局安装webpack以及webpack-cli,当在命令行执行webpack时,会从依赖目录中找到对应依赖并加载执行,直接通过npm全局下载

npm install webpack webpack-cli –g

3.配置详解:

3.1 配置概述

webpack的配置繁多,本文先做一些入门级的叙述。webpack的配置代码写在webpack.config.js中,打包过程主要有以下关键步骤:

  1. 指定入口:首先,需要告诉webpack在众多文件中,从哪个文件开始入手,找到入口后,webpack会根据入口文件所引入(依赖)的文件,依次找到该文件进行打包,逐层往下;
  2. 指定出口:打包完毕后的文件被保存的位置
  3. loader:loader是使得webPack具有打包和编译非js文件的功能,如css-loader等,所有loader通过npm的形式从npm仓库直接下载
  4. plugin:plugin是插件,从npm仓库直接下载,其作用为在webpack的生命周期中,利用某些插件对输出做一些特定处理,这样说比较抽象,可以结合下面代码实例理解。
  5. 其他功能:如分包、热更新等,后续可以详细研究

3.2 代码

直接通过代码及详细的代码注释来阐述配置

const path = require('path')
const  { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { DefinePlugin } = require('webpack')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader/dist/index')

module.exports = {
  // 打包模式:分为开发模式和生产模式,webpack会据此执行不同操作
  mode: 'development',
  // 是否开启浏览器的devtool,可以便于在浏览器调试时查看源码
  devtool: 'source-map',
  // 监听各依赖文件变化,不需要每次都重新执行npm run build
  // watch: true,
  // 打包入口文件
  entry: './src/main.js',
  // 打包出口:包括路径及文件名
  output: {
    path: path.resolve(__dirname,'./build'),
    filename:'js/bundle.js'
  },
  devServer: {
    proxy: {
       //现在,对/api/users的请求会转发到 `http://localhost:8888/api/users`。
      "/api": {
        target: "http://localhost:8888",
        // 如果希望请求路径不包含api(api会随意字符),则需将路径重写
        pathRewrite: {
          "^/api": ""
        },
        // 默认情况下,将不接受在 HTTPS 上运行且证书无效的后端服务器。 如果需要,这样配置:
        secure: false,
        // 默认情况下,代理时会保留主机头的来源,可以将 `changeOrigin` 设置为 `true` 以覆盖此行为
        changeOrigin: true
      }
    }
    // 静态资源的存放目录
    static: {
      directory: path.join(__dirname, 'public'),
    },
    // 支持热替换,每次只刷新代码有变化的模块,不用刷新整个浏览器
    hot:true,
    // 配置端口号
    port: 8610,
    // 是否自动打开浏览器
    open: true,
    // 是否开启gzip压缩,默认为开启
    compress: false
  },
  // 解析相关配置
  resolve: {
    // extensions是解析到文件时自动添加扩展名
    extensions: ['.js', '.json', '.wasm', '.vue'],
    // 配置路径别名,便于访问目录
    alias: {
      'js': path.resolve(__dirname, 'src/js')
    }
  },
  // 所有的loader放在module下的rules中
  /*
      1.test的值为匹配所有以×××结尾的文件;use的值为使用到的loader
      2.如下使用到了css-loader、less-loader、style-loader、babel-loader、vue-loaderdeng
  */
  module: {
    rules: [
      {
        test: /\.css$/,
        use:[
          "style-loader",
          "css-loader"
        ]
      },
      {
        test: /\.less$/,
        use: [
          "style-loader",
          "css-loader",
          "less-loader"
        ]
      },
      {
        test: /\.jpe?g|png|gif|svg$/,
        // type设置为asset,则会识别为资源,不用loader
        type: 'asset',
        // 对于图片,自定义打包输出路径
        generator: {
          filename: 'img/[name]-[hash:6][ext]'
        },
        // 如果该模块源码大小小于maxSize,那么模块会被作为一个 Base64 编码的字符串注入到包中, 否则模块文件会被生成到输出的目标目录中。
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024
          }
        }
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        type: 'asset/resource',
        generator: {
          filename: 'font/[name]-[hash:6][ext]'
        },
      },
      {
        test: /\.js*/,
        // 注意:这里除了下载babel-loader外,还需下载@babel/core,使用npm install babel-loader @babel/core
        use: ["babel-loader"]
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      }
    ]
  },
  plugins: [
    // 打包时,自动删除dist文件夹
    new CleanWebpackPlugin(),
    // 自动在打包出口文件夹以指定文件为模板生成index.html文件
    new HtmlWebpackPlugin({
      template: "./public/index.html",
      title: 'ddd'
    }),
    // DefinePlugin允许在编译时创建配置全局常量,是webpack内置的插件
    new DefinePlugin({
      BASE_URL: "'./'",
      // 适配vue2的配置写法
      __VUE_OPTIONS_API__: true,
      // 线上环境是否开启devtool
      __VUE_PROD_DEVTOOLS__: false
    }),
    // public的目录下的文件会被复制到打包出口的文件夹中
    new CopyWebpackPlugin({
      patterns: [
        {
          from: 'public',
          to:'./',
          globOptions: {
            ignore: '**/index.html'
          }
        }
      ]
    }),
    // 注意,使用vue-loader外,还需npm install @vue/compiler-sfc -D 用于解析template;并且还需引入VueLoaderPlugin并配置才可以正常解析Vue代码
    new VueLoaderPlugin()
  ]
}

使用如上配置文件,大家就可以在工作目录新建各种css文件、js文件、vue文件;然后使用webpack进行打包,看下能否正常运行了

3.3 代码文件分离

到这里大家已经可以正常使用webpack打包文件了。不过我们可以再做一些优化。如大家所知,前端代码会运行在开发环境和生产环境,而针对两种不同环境,有一些不同的配置,比如针对跨域的配置,生产环境则不需要。因此我们可以将配置文件进行分离,不同环境的公用配置保存到webpack.com.config.js;生产环境的特有配置保存到webpack.prod.config.js;开发环境的特有配置保存到webpack.dev.config.js。使用时利用webpack提供的merge操作将公有配置和特有配置进行合并。

3.3.1 webpack.com.config.js

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { DefinePlugin } = require('webpack')
const { VueLoaderPlugin } = require('vue-loader/dist/index')

module.exports = {
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname,'../build'),
    filename:'js/bundle.js'
  },
  resolve: {
    extensions: ['.js', '.json', '.wasm', '.vue'],
    alias: {
      'js': path.resolve(__dirname, '../src/js')
    }
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use:[
          "style-loader",
          "css-loader"
        ]
      },
      {
        test: /\.less$/,
        use: [
          "style-loader",
          "css-loader",
          "less-loader"
        ]
      },
      {
        test: /\.jpe?g|png|gif|svg$/,
        type: 'asset',
        generator: {
          filename: 'img/[name]-[hash:6][ext]'
        },
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024
          }
        }
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        type: 'asset/resource',
        generator: {
          filename: 'font/[name]-[hash:6][ext]'
        },
      },
      {
        test: /\.js*/,
        use: ["babel-loader"]
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./public/index.html",
      title: 'ddd'
    }),
    new DefinePlugin({
      BASE_URL: "'./'",
      __VUE_OPTIONS_API__: true,
      __VUE_PROD_DEVTOOLS__: false
    }),
    
    new VueLoaderPlugin()
  ]
}

3.3.2 webpack.dev.config.js

const path = require('path')
const { merge } = require('webpack-merge')
const commonConfig = require('./webpack.comm.config')

const devConfig = {
  mode: 'development',
  devtool: 'source-map',
  devServer: {
    proxy: {
      "/api": {
        target: "http://localhost:8888",
        pathRewrite: {
          "^/api": ""
        },
        secure: false,
        changeOrigin: true
      }
    }
    static: {
      directory: path.join(__dirname, 'public'),
    },
    hot:true,
    port: 8610,
    open: true,
    compress: false
  },

}
// 合并配置
module.exports = merge(commonConfig, devConfig)

3.3.3 webpack.prod.config.js

const  { CleanWebpackPlugin } = require('clean-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')

const { merge } = require('webpack-merge')
const commonConfig = require('./webpack.comm.config')

const prodConfig = {
  mode: 'production',
  plugins: [
    new CleanWebpackPlugin(),
    new CopyWebpackPlugin({
      patterns: [
        {
          from: './public',
          to:'./',
          globOptions: {
            ignore: '**/index.html'
          }
        }
      ]
    }),
  ]
}

module.exports = merge(commonConfig, prodConfig)

然后命令行执行命令的时候,在package.json中修改命令,以读取对应配置文件

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

4.总结

本文主要是根据coderwhy老师的课程、官方文档的阅读以及自己的一些理解书写,希望可以给大家提供一点帮助,如果觉得有收获的,动起小手点点赞吧,学习前端的路上,大家一起加油!