前端进阶(二)webpack开发服务器环境配置

harry发布

# webpack开发服务器

webpack 使用 babel 处理高版本的 js 语法

babel 的介绍 => 用于处理高版本 js语法 的兼容性

  1. 安装包
      yarn add -D babel-loader @babel/core @babel/preset-env
  2. 配置规则
      module: {
        rules: [
          {
            test: /.js$/,
            exclude: /(node_modules|bower_components)/,
            use: {
              loader: 'babel-loader',
              options: {
                presets: ['@babel/preset-env']
              }
            }
          }
        ]
      }

webpack-dev-server自动刷新

  1. 下载
yarn add webpack-dev-server -D
  1. 配置scripts
scripts: {
    "build": "webpack --config webpack.config.js"
    "dev": "webpack-dev-server --config webpack.config.js"
}
  1. webpack-dev-server 的配置
module.exports = {
  ...
    devServer: {
    port: 3000, // 端口号
    open: true // 自动打开浏览器
    }
}

生产环境 和 开发环境

生产环境和开发环境刚好相反,开发环境在本地运行,而生产环境是要产出运行在线上服务器面向用户使用的代码,因此两者的构建目标差异很大,比如打包后的文件在生产环境中要尽可能的小,逻辑代码分离,优化静态资源(压缩图片)等。

因此开发环境和生产环境不能共用一份webpack配置文件,需要分别指定

但是两个环境还是有很多配置可以共用的,比如entry、output、module等,因此可以把公共部分的配置抽离出来放到一个独立的文件然后进行合并,我们可以使用webpack-merge工具来进行合并。

注意: entry、output、module这些配置在我们当前示例通用,但未必适合所有项目。

安装依赖

yarn add webpack-merge -D

开始拆分webpack.config.js文件,拆分后这个文件就不要了。

新建config文件夹:

- webpack-demo
  - config              // 存放配置文件的文件夹
    - webpack.base.js   // 公共的配置
    - webpack.dev.js    // 开发环境的配置
    - webpack.pro.js    // 生成环境的配置

  - // 其他文件

配置文件

config/webpack.base.js

// 存放公共的部分
const path = require('path')

// 引入自动生成 html 的插件
const HtmlWebpackPlugin = require('html-webpack-plugin')

// 引入分离 css 文件的 模块
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

// 导入清除插件, 可以在每次打包之前, 清除 dist目录的内容
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

// 配置webpack的配置文件, 需要将配置的对象导出, 给webpack使用
module.exports = {
  // 入口 entry, 从哪个文件开始打包
  entry: './src/main.js',

  // 出口 output, 打包到哪里去
  output: {
    // 打包输出的目录 (输出的目录必须是一个绝对路径)
    path: path.join(__dirname, '../dist'),
    // 打包后生成的文件名
    filename: 'js/bundle.js'
  },

  // 配置module模块加载规则
  // 默认, webpack只认识json, javascript, 不认识其他文件, 如果希望打包处理其他文件, 需要配置对应loader
  module: {
    rules: [
      // (1) 配置css文件的解析
      {
        // 正则: 匹配所有以css结尾的文件
        test: /.css$/,
        // 实际处理顺序: 从右往左
        // css-loader 让webpack能够识别解析 css 文件
        // style-loader 通过动态的创建style标签的方式(js), 让解析后的css内容, 能够作用到页面中
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: '../',
            },
          }, 
          'css-loader'
        ]
      },
      // (2) 配置less文件的解析
      {
        test: /.less$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: '../',
            },
          }, 
          'css-loader', 
          'less-loader'
        ]
      },
      // (3) 配置图片文件的解析  i 表示忽视大小写  .PNG
      {
        test: /.(png|jpg|gif)$/i,
        use: [
          // url-loader 如果不配置, 默认都会将文件转成base64字符串的格式
          {
            loader: 'url-loader',
            // 8k以内, 转成base64, 节约请求次数, 8k以外, 单独一个文件请求
            options: {
              limit: 8 * 1024,
              // 配置输出的文件名
              name: '[name].[ext]',
              // 配置静态资源的引用路径
              publicPath: "../images/",
              // 配置输出的文件目录
              outputPath: "images/"
            }
          }
        ]
      },
      // (4) 配置新版本js文件的解析
      {
        test: /.js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      }
    ]
  },

  // 配置插件
  plugins: [
    // 自动生成 html 的插件
    new HtmlWebpackPlugin({ template: './public/index.html' }),

    // 分离css的插件, 定义打包好的文件的e存放路径和文件名
    new MiniCssExtractPlugin({ 
      filename:'css/index.css'
    }),

    // 清除dist目录的插件
    new CleanWebpackPlugin()
  ]
}

webpack.dev.js

// 存放开发模式下的配置 development
const base = require('./webpack.base.js')
// 用于合并webpack配置的插件
const merge = require('webpack-merge')

// merge 可以接受多个参数, 把参数对象合并成一个对象
// 后面的对象属性, 会覆盖前面的对象属性
module.exports = merge(base, {
  // 配置开发服务器
  devServer: {
    port: 3000, // 端口号
    open: true // 自动打开浏览器
  },
  mode: 'development'
})

webpack.pro.js

// 存放生产模式的配置 production
const base = require('./webpack.base.js')
// 用于合并webpack配置的插件
const merge = require('webpack-merge')

// merge 可以接受多个参数, 把参数对象合并成一个对象
// 后面的对象属性, 会覆盖前面的对象属性
module.exports = merge(base, {
  mode: 'production' // 声明当前是生产环境
})

注意: 拆分完webpack.config.js后可以把该文件删除了。

修改scripts启动命令,注意指定配置文件的路径变化

package.json

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

多入口多出口

多入口需要修改entry配置,在这之前我们都是把src/main.js打包成dist/bundle.js引入到项目中,那如果有多个main.js类型的文件需要引入呢? 就需要配置多入口

- webpack-demo
  - src
    - index.js
    - about.js

注意: index.js和about.js没有任何关系,都是独立的不相互引用。

src/index.js

var element = document.createElement("span");
element.innerHTML =  `hello`;
document.body.appendChild(element);

src/about.js

var element = document.createElement("div");
element.innerHTML =  `about`;
document.body.appendChild(element);

config/webpack.base.js

// 其他代码

module.exports = {
    // 用对象的方式配置多个入口
    entry: {
        index: "./src/index.js",
        about: "./src/about.js"
    },
    output: {
        // 修改输出路径和文件名,[name]是动态的,读取entry的属性
        path: path.join(__dirname, "../dist"),
        filename: "js/[name].bundle.js"
    },

    // 其他代码
}

我们执行npm run build命令,可以看到 dist 的结构如下

- webpack-demo
  - dist
    - js
      - index.bundle.js
      - about.bundle.js
    - index.html

提取公共模块

当在 index 和 about 这两个独立入口文件中, 如果引入了相同的模块, 这些模块会被重复打包, 我们需要提取公共模块!

将 jquery 库分别引入到 index.js 和 about.js 中。

const $ = require('jquery')

执行构建命令

yarn build

查看打包后的 about.bundle.jsindex.bundle.js 文件源码,会发现它们都把 jquery.js 打包进去了,这样做的后果不敢想象。所以我们需要把类似公共的依赖模块提取到一个单独的文件中。

config/webpack.base.js

// 其他代码

module.exports = {
    // 其他代码
    // + 提取公共模块配置
    optimization: {
        splitChunks: {
            chunks: 'all'   // 提取所有文件的共同模块
        }
    }
}

再次执行打包

yarn build

可以看到当前项目的公共模块 jquery 的内容已经被打包到一个 独立的 about~index.bundle.js文件中了,当然这个文件名可以通过配置修改的。

注意: 公共模块的大小必须大于 30kb才会被独立打包,jquery 的大小是 87kB。

分类: 前端

0 条评论

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用*标注