webpack从零开始配置大全

  • 由于webpack5刚刚发布,相关生态还不成熟,这里以webpack4的版本为例,
  • 为了避免插件版本的兼容问题,以下安装个别npm依赖时我会指定版本号。
  • 本文仅作为webpack学习之用,实际项目中还是更推荐使用成熟的脚手架搭建,然后根据学习的成果再去定制改造。
  • 示例代码已上传github:webpack-demo

一、基础

1、目录文件

新建一个文件夹作为示例项目,项目根目录运行命令初始化package.json:

npm init -y

然后按照以下目录先创建空文件:
webpack从零开始配置大全_第1张图片

2、entry和output

  • 安装webpack依赖
npm i -D [email protected] [email protected]
  • /config/webpack.base.config.js 写入内容:
const path = require('path')

module.exports = {
  entry: { // 入口配置
    app: 'src/index.js'
  },
  output: { // 出口配置
      filename: 'js/[name].[chunkhash:8].js',
      path: path.resolve(__dirname, '../dist'),
  }
}
  • package.json 里写入script命令:
"script": {
  "build": "webpack --config /config/webpack.base.config.js"
}
  • 然后就可以运行查看效果了:
npm run build
  • 正常的话,会在项目根目录生成dist文件夹,里面就是打包后的文件。

在这里插入图片描述

3、html-webpack-plugin

使用 html-webpack-plugin 插件来配置html模板文件的关联,这样打包后的js、css等会自动引入到html中,就可以访问html文件查看效果了。

  • 安装插件:
npm i -D [email protected]
  • /config/webpack.base.config.js 添加plugins,配置html-webpack-plugin:
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: ......,
  output: ......,
  // 在这里添加
  plugins: [
    new HtmlWebpackPlugin({
      template: 'public/index.html',
      inject: 'body',
      hash: false
    }),
  ],
}
  • /public/index.html 写入代码:



  
  
  
  Title


  
  • /src/index.js 写入代码:
console.log('小王子')
  • 最后运行命令打包:npm run build,打包后会在dist下生成index.html,打开该html查看控制台输出效果。

4、react及babel

用哪个框架都行,目的都是学习webpack的配置,以react示例。

  • 安装react依赖:
npm i -S react react-dom
  • /src/index.js 替换为以下代码:
import React from 'react'
import ReactDOM from 'react-dom'

function App () {
  return (
    
小王子
) } ReactDOM.render( , document.getElementById('root') )
  • 添加babel:

由于react使用的jsx语法,不是js标准语言语法,所以需要借助babel插件来转码,当然babel用处远不止这些,还需要babel将es6+代码转为兼容性更好的es5代码。
安装babel相关依赖:

npm i -D babel-loader @babel/core @babel/preset-env @babel/preset-react
  • babel.config.js 写入代码:
module.exports = {
  presets: [
    '@babel/preset-env', 
    '@babel/preset-react'
  ],
}
  • /config/webpack.base.config.js 添加module,配置babel的rules:
const path = require('path')

module.exports = {
  entry: ......,
  output: ......,
  plugins: ......,
  // 在这里添加代码
  module: {
    rules: [
      {
        test: /\.(js|jsx)?$/,
        options: {
          cacheDirectory: true
        },
        loader: 'babel-loader'
      }
    ]
  }
}
  • 运行 npm run build,然后打开打包后的index.html查看效果。

5、webpack-merge

webpack配置里可以指定mode属性来把运行环境划分为development和production,
使用webpack-merge插件可以针对不同mode环境使用不同的webpack配置,插件帮我们智能合并配置。

  • 安装依赖:
npm i -D [email protected]
  • /config/webpack.dev.config.js 写入代码:
const merge = require('webpack-merge')
const common = require('./webpack.base.config')

module.exports = merge(common, {
  mode: 'development',
  output: {
    filename: 'js/[name].[hash:8].js',
  },
})
  • /config/webpack.prod.config.js 写入代码:
const merge = require('webpack-merge')
const common = require('./webpack.base.config')

module.exports = merge(common, {
  mode: 'production',
})
  • package.json 里修改scripts命令:
"scripts": {
  "start": "webpack --config ./config/webpack.dev.config.js",
  "build": "webpack --config ./config/webpack.prod.config.js"
},

注意build命令里的webpack.base.config.js换成了webpack.prod.config.js。
这样就分了开发环境和生产环境。

6、clean-webpack-plugin

使用clean-webpack-plugin插件可以在build打包之前自动删除上次打包的dist文件夹,防止冗余文件的产生。

  • 安装依赖:
npm i -D clean-webpack-plugin
  • /config/webpack.prod.config.js 里添加plugins配置:
const merge = require('webpack-merge')
const common = require('./webpack.base.config')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = merge(common, {
  mode: 'production',
  // 在这里添加代码
  plugins: [
    new CleanWebpackPlugin(),
  ],
})
  • npm run build 查看dist文件夹还有没有之前遗留的js文件。

7、webpack-dev-server

使用webpack-dev-server插件,在webpack运行时自动启动一个本地服务器运行打包后的html文件,配合热更新,实现代码改动后实时查看效果。

  • 安装依赖:
npm i -D [email protected]
  • /config/webpack.dev.config.js 里添加devServer和plugins配置:
const merge = require('webpack-merge')
const common = require('./webpack.base.config')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = merge(common, {
  mode: 'development',
  output: {
    filename: 'js/[name].[hash:8].js',
  },
  // 在这里添加代码
  devServer: {
    contentBase: path.resolve(__dirname, '../dist'),
    open: true,
    port: 9000,
    compress: true,
    hot: true
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
  ],
})
  • package.json 里修改scripts的start命令:
"start": "webpack-dev-server --oneline --config ./config/webpack.dev.config.js",
  • npm start 查看效果。

8、devtool和source map

devtool用于配置source map选项,帮助我们调试时追踪原始源代码,有多重source map格式供选择,具体可以参考文档,综合构建速度和使用效果,一般选择 cheap-module-eval-source-map,各方面都比较均衡。

  • /config/webpack.dev.config.js 里添加devtool配置:
module.exports = merge(common, {
  mode: 'development',
  devtool: 'cheap-module-eval-source-map', // 在这里添加即可
  output: ......,
  devServer: ......,
  plugins: ......,
})
  • /src/index.js 里添加一条console语句:
import React from 'react'
import ReactDOM from 'react-dom'

console.log(123) // 在这里添加即可

function App () {
  ......
}
......
  • 在chrome控制台找到打印结果行,点击该行右侧的文件路径查看源代码,通过对比添加和不添加devtool时的源码来理解source map的作用。

9、style-loader、css-loader、less-loader

style-loader 用于创建样式标签引入css代码,不能单独使用;
css-loader 用于解析css文件生成css代码,给style-loader使用;
less-loader 用于将less文件转换为css文件,给css-loader使用;

  • 安装依赖:
npm i -D style-loader css-loader less less-loader
  • src文件夹下创建文件index.less:
@color: red;

.test {
  color: @color;
}
  • /src/index..js 引入该less使用:
import React from 'react'
import ReactDOM from 'react-dom'
import './index.less'

function App () {
  return (
    
小王子
) } ReactDOM.render( , document.getElementById('root') )
  • /config/webpack.base.config.js 里配置loader:
module.exports = {
  module: {
    rules: [
      ......
      // 接上,追加以下代码
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      {
        test: /\.less$/,
        use: ['style-loader', 'css-loader', 'less-loader']
      },
    ]
  }
}

rules里的use数组在解析时是按从右往左解析的,需要注意顺序。

10、postcss

postcss 是一个允许使用 JS 插件转换样式的工具集合;
postcss-loader 用于webpack中对css做进一步处理的loader;
autoprefixer 属于postcss的一个插件,配合postcss-loader可以自动给css样式添加浏览器前缀,以兼容低版本浏览器;
browserlist 用于指定项目运行的目标浏览器范围,能被autoprefixer和babel等识别,根据目标浏览器范围做兼容适配。

  • 安装依赖:
npm i -D postcss postcss-loader autoprefixer browserlist
  • /src/index.less添加样式:
@color: red;

.test {
  color: @color;
  display: flex;
  justify-content: center;
}
  • /config/webpack.base.config.js 里修改css和less的loader配置:
module.exports = {
  module: {
    rules: [
      ......
      // 修改css和less的loader配置
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader', 'postcss-loader']
      },
      {
        test: /\.less$/,
        use: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader']
      },
    ]
  }
}
  • 项目根目录新建文件 postcss.config.js:
module.exports = {
  plugins: {
    autoprefixer: {}
  }
}
  • package.json 里添加browserlist配置:
{
  "dependencies": ......,
  "devDependencies": ......,
  ---在这里追加---
  "browserslist": [
    "> 1% in CN",
    "last 2 versions"
  ]
}
  • npm start 运行,chrome开发者工具查看文字的css样式,看flex相关样式是否自动加上了浏览器前缀。

11、file-loader和url-loader

file-loader用于打包静态文件并将引入路径和js关联;
url-loader用于处理图片资源的打包,低于指定大小时会将资源转换为base64格式使用,其他情况处理和file-loader一样。

  • 安装依赖:
npm i -D file-loader url-loader
  • /config/webpack.base.config.js 里添加loader配置:
module.exports = {
  module: {
    rules: [
      ......
      // 接上,追加以下代码
      {
        test: /\.(jpe?g|png|gif)$/i,
        options: {
          esModule: false,
          limit: 4096, // 配置低于4k的图片会转为base64格式
        },
        loader: 'url-loader',
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/i, // 处理字体文件
        options: {
          esModule: false
        },
        loader: 'file-loader'
      },
    ]
  }
}

12、mini-css-extract-plugin

mini-css-extract-plugin用于将打包后的css单独抽离出来,webpack打包时默认是将css整合进js里通过动态创建style标签实现的,而这个插件将css剥离出来,能减少不必要的js代码及dom操作,提升页面加载性能。

  • 安装依赖:
npm i -D mini-css-extract-plugin
  • /config/webpack.base.config.js 里配置plugins和loader:
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = {
  plugins: [
    ......,
    // 接上,在这里追加
    new MiniCssExtractPlugin({
      filename: 'css/[name].[hash:8].css',
      chunkFilename: 'css/[id].[hash:8].css',
      ignoreOrder: true
    }),
  ],
  module: {
    rules: [
      // 修改css和less的loader,替换掉style-loader
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader']
      },
      {
        test: /\.less$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'less-loader']
      },
    ]
  }
}
  • npm run build 查看打包目录是否生成单独的css文件。

二、进阶

1、terser-webpack-plugin

terser-webpack-plugin 用于对js做代码压缩及代码混淆等处理,对es6+支持更好,替代以前的uglifyjs-webpack-plugin。

  • 安装依赖:
npm i -D [email protected]
  • /config/webpack.prod.config.js 里添加配置:
const TerserWebpackPlugin = require('terser-webpack-plugin')

module.exports = merge(common, {
  mode: 'production',
  plugins: ......,
  // 在这里添加
  optimization: {
    minimize: true,
    minimizer: [
      new TerserWebpackPlugin({
        parallel: true, // 使用多进程提高构建速度
        extractComments: false, // 禁止生成license文件
        terserOptions: {
          compress: { // 删除console.log代码
            drop_console: true,
            pure_funcs: ['console.log']
          },
          output: {
            comments: false // 删除注释代码
          }
        }
      }),
    ],
  },
})

2、optimize-css-assets-webpack-plugin

optimize-css-assets-webpack-plugin 插件用于对css文件做压缩处理,默认使用cssnano压缩。

  • 安装依赖:
npm i -D optimize-css-assets-webpack-plugin
  • /config/webpack.prod.config.js 里添加plugins:
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')

module.exports = merge(common, {
  plugins: [
    ......,
    // 接上,在这里追加
    new OptimizeCssAssetsPlugin(),
  ]
})
  • npm run build 查看打包后的css文件是否已被压缩。

3、DefinePlugin

DefinePlugin 是webpack内置的一个插件,允许创建一个在编译时可以配置的全局常量,配置后就可以在代码里使用这个常量了。

  • /config/webpack.base.config.js 里添加plugins:
const webpack = require('webpack')

module.exports = {
  plugins: [
    ......,
    // 接上,在这里追加
    new webpack.DefinePlugin({
      VERSION_H5: +new Date() // 这里添加了VERSION_H5
    }),
  ]
}

需要注意,如果给定义的常量赋值为string类型时需要带上原始引号,可以通过单引号包裹双引号的方式或通过JSON.stringify包裹,例如 '"abc"' 或 JSON.stringify('abc')

  • /src/index.js 里添加一条打印语句:
// 找个合适的地方添加就行
console.log(VERSION_H5)
  • npm start 查看chrome控制台输出结果是否符合预期

三、未完待续。。。


查看更多

你可能感兴趣的:(前端,javascript,react.js,webpack)