02webpack之常用配置

发布时间 2023-10-09 17:37:54作者: songxia777

1 webpack之配置css样式资源

1.1 下载安装项目依赖

# style-loader:创建style标签,将js中的样式资源插入进行,添加到head中生效
# css-loader:将css文件变成commonjs模块加载js中,里面内容是样式字符串
npm i style-loader css-loader -D

# 编译 sass 文件
npm i sass sass-loader  -D

# 编译 less 文件
npm i less less-loader  -D

# // CSS抽离插件,会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,并且支持 CSS 和 SourceMaps 的按需加载
npm i mini-css-extract-plugin -D

# 压缩 css 文件
npm i css-minimizer-webpack-plugin -D

# 自动添加厂商前缀 css兼容性处理
npm i postcss postcss-loader postcss-preset-env -D

1.2 配置 webpack.config.js

/**
 *  所有构建工具都是基于nodejs平台运行的,所以模块化默认采用commonJS
 *  配置 postcss-loader 需要搭配 postcss.config.js
 */

// path模块的resolve方法,主要是用来动态的拼接绝对路径
const { resolve } = require('path');

// CSS抽离插件
// 本插件会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,并且支持 CSS 和 SourceMaps 的按需加载
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

// 引入插件
const HtmlWebpackPlugin = require('html-webpack-plugin');

// 2.  css压缩插件
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

module.exports = {
  entry: './src/index.js',
  output: {
    // 输出文件名
    filename: 'build.js',
    // 输出文件路径
    path: resolve(__dirname, 'dist'),
    // 每次编译打包都会重新清除 dist,然后再重新生成
    clean: true
  },
  module: {
    rules: [
      // 配置编译css文件
      /* 使用哪些loader处理
         use数组中loader的执行顺序:从右到左,从下到上 依次执行
         style-loader:创建style标签,将js中的样式资源插入进行,添加到head中生效
         css-loader:将css文件变成commonjs模块加载js中,里面内容是样式字符串
      */
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader'
        ]
      },
      // 配置编译sass 或 scss 文件,依赖项: sass sass-loader 
      {
        test: /\.s[a|c]ss$/i,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'sass-loader',
          'postcss-loader'
        ]
      },
      // 配置编译 less 文件,依赖项: less less-loader 
      {
        test: /\.less$/i,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'less-loader',
          'postcss-loader'
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    // 对抽离出的css文件进行重命名
    new MiniCssExtractPlugin({
      filename: 'css/[name].[contenthash].css',
      chunkFilename:'css/[name].[contenthash].chunk.css'  
    })
  ],
  optimization: {
    // 默认是只在生产环境下 压缩,如果要在开发环境下压缩,需要开启 optimization.minimize为true 
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin(),
    ],
  },
  mode: 'development'
}

在生产环境中,css 是默认压缩的,可以不开启 minimize: true

在生产环境中,html和js也是默认压缩的,所以也不需要进行额外的配置

postcss.config.js 配置

module.exports = {
  plugins: [
    // 使用 postcss预设,可以解决大多数的css兼容性问题
    require('postcss-preset-env')
  ]
}

可以在 package.json 设置 browserslist

"browserslist":[
	"1%",
	"last 2 version",
	"not dead"
]

配置文件 设置 browserslist(推荐)

一些常见的配置,例如 postcss,babel 都会共用这个 .browserslistrc 里面的浏览器配置

创建一个文件 .browserslistrc

Android 4.1
iOS 7.1
Chrome > 31
ff > 31
ie >= 8

1.3 loader和plugin介绍

3.1 css-loader

css-loader是允许在js中import一个css文件,会将css文件当成一个模块引入到js文件中

3.2 style-loader

style-loader能够在需要载入的html中创建一个 <style></style>标签,标签里的内容就是CSS内容

3.3 sass-loader

主要功能是编译sass 或 scss 文件

3.4 less-loader

主要功能是编译 less 文件

3.5 mini-css-extract-plugin

CSS抽离插件,会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,并且支持 CSS 和 SourceMaps 的按需加载

3.6 css-minimizer-webpack-plugin

CSS压缩插件

3.7 postcss-loader

自动添加厂商前缀

2 webpack之常用插件

2.1 clean-webpack-plugin

默认webpack打包后的dist文件夹下的js文件并不会被自动删除,如果重新打包,会生成新的文件,旧的文件仍然会存在

clean-webpack-plugin 插件 主要是用来清除重复文件,生成最新的的插件

就是说在编译文件的时候,先把 build或dist (就是放生产环境用的文件) 目录里的文件先清除干净,再生成新的带有hash值的文件

npm i clean-webpack-plugin -D

webpack5 中只要在 output 中 配置 clean:true 即可

配置 webpack.config.js

 const { CleanWebpackPlugin } = require('clean-webpack-plugin');
//插件配置
plugins: [
  new CleanWebpackPlugin()
],

2.2 html-webpack-plugin

2.2.1 主要功能

1、 可以使用模板动态生成html文件并自动引入js入口文件

2、 静态文件无需加载js或css文件,通过设置入口文件可以将js文件自动添加进去,而相关的css文件在js中导

3、 同时修改生成的js文件命名规则,利用hash码命名js文件

4、 没有改动时可以让浏览器缓存内容,当有改动重新部署后可以让浏览器缓存失效

2.2.2 安装和配置

npm i html-webpack-plugin -D

webpack.config.js 配置

const { resolve } = require('path');

// 引入插件
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    // 输出文件名
    filename: 'build.js',
    // 输出文件路径
    path: resolve(__dirname, 'dist'),
    // 每次编译打包都会重新清除 dist,然后再重新生成
    clean: true
  },
  plugins: [
    // 配置   HtmlWebpackPlugin
    new HtmlWebpackPlugin({       
     // 复制 './src/index.html' 文件,并自动引入打包输出的所有资源(JS/CSS)
      template: './src/index.html', // 模板文件
     // 编译后的文件名称,默认为index.htmls
      filename: 'app.html',
      title: 'webpack html插件',
      hash: true,
      // 设置所有资源文件注入模板的位置。可以设置的值  true|'head'|'body'|false,默认值为 true
      inject: 'body',
      hash: true, // 给静态文件添加hash值,和output-filename中指定chunkhash效果差不多
      showErrors: true, // 如果编译出错,错误直接显示在页面中,方便排错
        
      chunks: ["jquery"] // 指定哪些静态文件打包进H5,
      excludeChunks: ["home"] // 指定哪些静态文件不需要打包进H5
                          
      minify: {
          collapseWhitespace: true, // 去掉所有空格
          removeAttributeQuotes: true, // 去掉所有不必要的引号
          removeComments:true // 移除注释                
       },
       cache: true, // 文件变化才重新编译
      
       chunksSortMode: "dependency", // 引入顺序: 根据依赖关系
       xhtml: true // 兼容xhtml模式编译H5
    }),
  ],
  mode: 'development'
}

2.2.3 常用的参数

title

打包生成的html文档的标题

配置该项,它并不会替换指定模板文件中的title元素的内容,除非html模板文件中使用了模板引擎语法来获取该配置项值
<title><%= htmlWebpackPlugin.options.title %></title>

template:模板路径

指定你生成的文件所依赖哪一个html文件模板,模板类型可以是html、jade、ejs等

但是要注意的是,如果想使用自定义的模板文件的时候,你需要安装对应的loader

为template指定的模板文件没有指定任何loader的话,默认使用ejs-loader。如template: './index.html',若没有为.html指定任何loader就使用ejs-loader

filename:一般是相对路径

输出文件的文件名称,默认为index.html,还可以为输出文件指定目录位置(例如'html/index.html')

filename配置的html文件目录是相对于webpackConfig.output.path路径而言的,不是相对于当前项目目录结构的

指定生成的html文件内容中的link和script路径是相对于生成目录下的,写路径的时候一般是生成目录下的相对路径

templateContent: string|function

可以指定模板的内容,不能与template共存。配置值为function时,可以直接返回html字符串,也可以异步调用返回html字符串

minify: {....}|false

传递 html-minifier 选项给 minify 输出,false就是不使用html压缩

minify: {
	collapseWhitespace: true, //打包后是否删除空格(压缩)
	removeAttributeQuotes: true // 移除属性的引号
},
  • caseSensitive(默认false):以区分大小写的方式处理属性(适用于定制的HTML标记)

  • collapseBooleanAttributes(默认false):从布尔属性中省略属性值

  • collapseInlineTagWhitespace Don't leave any spaces between display:inline;elements when collapsing. Must be used in conjunction with collapseWhitespace=true false

  • collapseWhitespace 在显示之间不要留下任何空格:内联;崩溃时的元素。必须与折叠空间结合使用=true ? false

  • conservativeCollapse 总是折叠到1个空间(永远不要完全删除它)。必须与折叠空间结合使用=true ? false

  • customAttrAssign 允许支持自定义属性分配表达式的正则表达式数组。 (e.g. '<div flex?="{{mode != cover}}">') [ ]

  • customAttrCollapse Regex指定自定义属性以从(例如/ng-class/)删除新行。

  • customAttrSurround 允许支持自定义属性包围表达式的正则表达式数组(e.g. <input {{#if value}}checked="checked"{{/if}}>) [ ]

  • customEventAttributes 允许为minifyJS支持自定义事件属性的正则表达式数组(例如,ng-click) [ /^on[a-z]{3,}$/ ]

  • decodeEntities 尽可能使用直接的Unicode字符。false

  • html5 根据HTML5规范分析输入。 true

  • ignoreCustomComments 当匹配时,允许忽略某些注释的正则表达式数组。 [ /^!/ ]

  • ignoreCustomFragments 当匹配时,允许忽略某些片段的正则表达式数组(例如,{ {…} },等等)。 [ /<%[\s\S]?%>/, /<?[\s\S]??>/ ]

  • includeAutoGeneratedTags 插入由HTML解析器生成的标记。 true

  • keepClosingSlash 保留单例元素的末尾斜杠。 false

  • maxLineLength 指定最大行长度。压缩的输出将在有效的HTML分割点上被换行。

  • minifyCSS 缩小CSS样式元素和样式属性(usesclean-css) false (could betrue, Object,Function(text))

  • minifyJS 在脚本元素和事件属性中缩小JavaScript(使用UglifyJS) false (could betrue, Object,Function(text, inline))

  • minifyURLs 在各种属性中缩小url(使用relateurl) false (could beString, Object,Function(text))

  • preserveLineBreaks 当标记之间的空格包括换行符时,总是崩溃到1行中断(永远不要完全删除)。必须与折叠空间结合使用=true ? false

  • preventAttributesEscaping 防止属性值的溢出。 false

  • processConditionalComments 通过minifier处理条件评论的内容。 false

  • processScripts 通过minifier(例如text/ng-template、text/x-handlebars-template等)来处理脚本元素类型的字符串数组。 [ ]

  • quoteCharacter 用于属性值的引用类型('or')

  • removeAttributeQuotes 在可能的情况下删除引号。 false

  • removeComments 带HTML注释 false

  • removeEmptyAttributes 删除所有的属性,只有whitespace-only的值。 false (could betrue,Function(attrName, tag))

  • removeEmptyElements 删除所有含有空内容的元素。 false

  • removeOptionalTags 删除可选的标记 false

  • removeRedundantAttributes 当值匹配默认值时删除属性。 false

  • removeScriptTypeAttributes 从脚本标签中删除type="text/javascript"。其他类型的属性值是完整的。false

  • removeStyleLinkTypeAttributes 从style和link标签中删除type="text/css"。其他类型的属性值是完整的。 false

  • removeTagWhitespace 尽可能在属性之间移除空间。注意,这将导致无效的HTML! false

  • sortAttributes 根据频率属性进行排序 false

  • sortClassName 按频率分类样式类。 false

  • trimCustomFragments 在ignoreCustomFragments周围调整空白区域。 false

  • useShortDoctype 用short (HTML5) doctype替换doctype。 false

chunks

允许插入到模板中的一些chunk,不配置此项默认会将entry中所有的thunk注入到模板中

在配置多个页面时,每个页面注入的thunk应该是不相同的,需要通过该配置为不同页面注入不同的thunk

chunks主要是选择使用你页面中呀加入的js

plugins: [
    new httpWebpackPlugin({
    chunks: ['index','main']
    })
]

那么编译后:

<script type=text/javascript src="index.js"></script>
<script type=text/javascript src="main.js"></script>

excludeChunks:排除掉一些js,用来配置不允许注入的thunk

chunksSortMode: none | auto| function,默认auto

允许指定的thunk在插入到html文档前进行排序。

function值可以指定具体排序规则

auto基于thunk的id进行排序

none就是不排序

inject有四个值: true body head false

向template或者templateContent中注入所有静态资源,不同的配置值注入的位置不经相同

true 默认值或body,所有JavaScript资源插入到body元素的底部

head script标签位于html文件的 head中

false 不插入生成的js文件,这个几乎不会用到的

favicon

添加特定favicon路径到输出的html文档中,这个同title配置项,需要在模板中动态获取其路径值

结果是将生成的html文件生成一个 favicon ,值是一个路径 :favicon: 'path/to/my_favicon.ico',然后再生成的html中就有了一个 link 标签

<link rel="shortcut icon" href="example.ico">

cache:true|fasle, 默认true

表示内容变化的时候生成一个新的文件

如果为true表示在对应的thunk文件修改后就会emit文件

hash:布尔值,默认false

是否为所有注入的静态资源添加webpack每次编译产生的唯一hash值,添加hash形式如下所示:

html <script type="text/javascript" src="common.js?a3e1396b501cdd9041be"></script>

xhtml: true|fasle, 默认false

是否渲染link为自闭合的标签,true则为自闭合标签

showErrors: true|false,默认true

是否将错误信息输出到html页面中

配置多个html页面例子(重点)

应用中配置了三个入口页面:index.html、course.html、about.html;并且每个页面注入的thunk不尽相同;

类似如果多页面应用,就需要为每个页面配置一个;

// 需要暴露在全局(模块的导出)
// __dirname目录就是E:\MyLocalProject\webpackDemo
const path = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
entry: {
    general: './src/skin/general/js/general.js',
    index: './src/skin/index/js/index.js',
    course: './src/skin/course/js/index.js',
    about: './src/skin/about/js/index.js',
},
output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'skin/[name]/[name].js',  //必须是相对路径
    publicPath: '../../'
},
module: {
    rules: [
        //配置babel,自动编译es6语法
        {
            test: /\.js$/,
            exclude: /(node_modules)/,
            loader: 'babel-loader'
        },

    ]
},
//插件的相关配置
plugins: [
    //配置html文件
    new htmlWebpackPlugin({
        template: path.join(__dirname, '/src/static/index.html'),
        filename: 'static/index.html',
        minify: {
            collapseWhitespace: true
        },
        hash: true,
        favicon: 'favicon.ico',
        chunks: ['general', 'index']
    }),
    new htmlWebpackPlugin({
        template: path.join(__dirname, '/src/static/course/index.html'),
        filename: 'static/course/index.html',
        minify: {
            collapseWhitespace: true,
        },
        hash: true,
        favicon: 'favicon.ico',
        chunks: ['general', 'course']
    }),
    new htmlWebpackPlugin({
        template: path.join(__dirname, '/src/static/about/index.html'),
        filename: 'static/about/index.html',
        minify: {
            collapseWhitespace: true
        },
        hash: true,
        chunks: ['general', 'about'],
        favicon: 'favicon.ico'
    }),
]
}

使用glob 扫描路径,自动配置html (重点)

    // __dirname目录就是E:\MyLocalProject\webpackDemo
const path = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')

//扫描入口目录static的路径
const glob = require("glob");
const staticHtmlPath = glob.sync('src/static/**/*.html');

//定义入口对象entrys
const entrys = {};
//设置公共的js入口文件
const commonJSObj = {
  general: './src/skin/general/js/general.js',
}
Object.assign(entrys, commonJSObj)

//定义html-webpack-plugin配置项
const htmlCfgs = [];
const htmlCfgsObj = {};
staticHtmlPath.forEach((filePath) => {
  let path = filePath.split('/')
  let pathLength = path.length
  //获取文件名
  let filename = path[pathLength - 1].split('.')[0]

  //动态配置入口文件路径
  let entryJSName = path[pathLength - 2] + '-' + filename
  entrys[entryJSName] = './src/skin/' + path[pathLength - 2] + '/js/' + filename + '.js';
  htmlCfgs.push( //动态配置入口文件插件
    new htmlWebpackPlugin({
      template: filePath,
      filename: filePath.replace('src', ''),
      minify: {
        collapseWhitespace: true
      },
      hash: true,
      favicon: 'favicon.ico',
      chunks: [entryJSName, 'general'],
    })
  )
});

module.exports = {
  devtool: 'inline-source-map',
  // 入口
  entry: entrys,
  // 出口
  output: {
    path: path.resolve(__dirname, 'dist'), //必须是绝对路径
    filename: 'skin/[name]/[name].js',  //必须是相对路径
    publicPath: '../../'
  },
  // 开发服务器
  devServer: {},
  // 模块配置
  module: {
    rules: [
      //配置babel,自动编译es6语法
      {
        test: /\.js$/,
        exclude: /(node_modules)/,
        loader: 'babel-loader'
      },
    ]
  },
  //插件配置
  plugins: htmlCfgs,
  //配置解析
  resolve: {}
}

参考文章:
https://www.cnblogs.com/wonyun/p/6030090.html

2.3 purgecss-webpack-plugin

主要作用是将项目中没有用到的css代码或js代码过滤掉,不将其打包到文件中

npm i purgecss-webpack-plugin -D

# glob-all用于处理多路径文件,使用purifycss的时候要用到glob.sync方法
npm i glob-all -D

webpack.config.js 配置

const PurgeCSSPlugin = require('purgecss-webpack-plugin')
const glob = require('glob-all');

// 在 plugins中的配置
new PurgeCSSPlugin({
    paths: glob.sync([ // 传入多文件路径
        path.resolve(__dirname, './*.html'), // 处理根目录下的html文件
        path.resolve(__dirname, './src/*.js') // 处理src目录下的js文件
    ])
})

2.4 terser-webpack-plugin

主要功能是:压缩 JS文件

npm i -D terser-webpack-plugin

webpack.config.js 配置

// JS压缩
const TerserPlugin = require('terser-webpack-plugin')

module.exports = {

  entry: './src/index.js',

  output: {
    filename: 'js/[name].[contenthash:6].js',
    path: resolve(__dirname, '../dist'),
    // 每次编译打包都会重新清除 dist,然后再重新生成
    clean: true
  },
  optimization: {
    // JS 压缩配置
    minimize: true,
    minimizer: [
      new TerserPlugin()
    ],
  }
}

2.5 webpack-bundle-analyzer

webpack 性能分析插件

npm i -D webpack-bundle-analyzer

webpack.config.js配置

// 性能分析
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {

  entry: './src/index.js',

  output: {
    filename: 'js/[name].[contenthash:6].js',
    path: resolve(__dirname, '../dist'),
    // 每次编译打包都会重新清除 dist,然后再重新生成
    clean: true
  },
  
  plugins: [
    new BundleAnalyzerPlugin()
  ],
}

2.6 cross-env 全局变量

设置环境变量

package.json设置

 "scripts": {
    "dev": "cross-env NODE_ENV=ANA webpack --env development"
  },

webpack.config.js 设置 全局变量

const { resolve } = require('path');

const Webpack = require('webpack')

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'js/[name].[contenthash:6].js',
    path: resolve(__dirname, '../dist'),
    // 每次编译打包都会重新清除 dist,然后再重新生成
    clean: true
  },
  plugins: [
    // 配置环境变量 为 全局可用 变量
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
    })
  ]
}

3 webpack 之 资源模块 配置

资源模块(asset module)是一种模块类型,它允许使用资源文件(字体,图标等)而无需配置额外 loader

资源模块一般是指 一些常用图片、字体、图标、json和txt等文件

目前webpack5通常使用以下 4 种模块类型来处理资源模块

  • asset/resource 发送一个单独的文件并导出 URL。之前通过使用 file-loader 实现。相当于直接复制文件
  • asset/inline 导出一个资源的 data URI。之前通过使用 url-loader 实现。直接生成 base64 格式的图片
  • asset/source 导出资源的源代码。之前通过使用 raw-loader 实现。
  • asset 在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用 url-loader,并且配置资源体积限制实现。根据配置,可以在复制文件和生成 base64 文件之前自动切换

3.1 webpack.config.js 配置

一些常用资源模块的配置

const path = require('path');
const HtmlWbpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'build.js',
    path: path.resolve(__dirname, 'build'),
    clean: true,
    // 设置 资源模块的打包输出路径 (优先级低于generator)
    //assetModuleFilename: 'assets/images/[contenthash][ext][query]'
  },
  module: {
    rules: [
      {
        test: /\.(scss|css)$/,
        use: ['style-loader', 'css-loader', 'sass-loader']
      },
      // 1.  图片资源模块:常见格式的图片、svg等
      {
        test: /\.(png|jpg|gif|svg|jpeg)$/i,
        type: 'asset',
        generator: {
          // 生成资源名称设置:以下3种都可以
          filename: 'assets/images/[name].[contenthash][ext]'
          // filename: 'assets/images/[contenthash][ext]',
          // filename: 'assets/images/[hash][ext][query]'
        },
        parser: {
          dataUrlCondition: {
            // 如果 资源的大小 小于 8KB,就转换为 base64位图的方式
            maxSize: 8 * 1024
          }
        }
      },
      // 2.  处理html中加载的img 标签图片 html-withimg-loader
      {
        test: /\.html$/,
        loader: 'html-withimg-loader'
      },

      // 3.  iconfont资源模块
      // 不需要做处理,直接输出,所以可以使用 asset/resource 资源类型  
      // 注意:使用的时候,一定要引入 iconfont.css 文件  
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/i,
        //文件打包方式
        type: 'asset/resource',
        generator: {
          // 生成资源名称设置:以下3种都可以
          filename: 'assets/[contenthash][ext]',
        }
      },

      // 4.  资源模块:*.txt *.json等文件
      {
        test: /\.(txt|json)$/i,
        type: 'asset/source',
        generator: {
          // 生成资源名称设置:以下3种都可以
          filename: 'assets/[contenthash][ext]',
        }
      },
    ]
  },
  plugins: [
    new HtmlWbpackPlugin({
      template: './src/index.html',
      inject: 'body'
    })
  ],
  mode: 'development'
}

3.2 json5 资源的配置

const { resolve } = require('path');
const HtmlWbpackPlugin = require('html-webpack-plugin');

const json5 = require('json5');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'build.js',
    path: resolve(__dirname, 'build'),
    clean: true,
  },
  module: {
    rules: [
      {
        test: /\.json5$/i,
        type: 'json',
        parser: {
          parse: json5.parse
        },
      },
    ]
  },
  plugins: [
    new HtmlWbpackPlugin({
      template: './src/index.html',
      inject: 'body'
    })
  ],
  mode: 'development'
}

4 webpack 之 JS 模块 配置

4.1 babel 语法兼容

4.1.1 下载安装项目依赖

# 基础包
npm i babel-loader @babel/core @babel/preset-env -D 

# 处理 Promise 中的 async/await 
npm i @babel/runtime @babel/plugin-transform-runtime -D

# 是专门用来做 ES6 以及以上 API 的 polyfill
npm i core-js -D

4.1.2 babel.config.json 配置文件

{
  "presets": [
    [
      "@babel/preset-env",
      {
        // "targets": {
        //   "ie": "8", //这个是自己添加的,最好是加上
        //   "edge": "17",
        //   "firefox": "60",
        //   "chrome": "67",
        //   "safari": "11.1"
        // },
        "useBuiltIns": "usage", // 按需加载
        "corejs": 3
      }
    ]
  ],
  "plugins": [
    "@babel/plugin-transform-runtime"
  ],
  // 开启babel缓存-优化构建效率, 第二次构建时,会读取之前的缓存
   cacheDirectory: true,
   // 关闭缓存文件压缩 
   cacheCompression:false  
}

/*
useBuiltIns
	默认是false 不对当前 js 做 polyfill 的填充
	usage:按需加载,依据用户源代码中使用的新语法按需填充
	entry:依据当前我们根据 browserslist 中我们筛选出来的浏览器 进行填充
*/

targets 也可以不设置,因为可以共用 browserslist 里面的设置

4.1.3 webpack.config.js 配置

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'build.js',
    path: resolve(__dirname, 'build'),
    clean: true
  },
  devtool: 'inline-source-map',
  module: {
    rules: [
      // 配置 babel-loader
      {
        test: /\.js$/,
        // 排除  node_modules 目录下的js文件  
        exclude: /node_modules/,
        // 只解析 src 目录里面的js   
        // include:resolve(__dirname,'src'),
        // 优先执行  
        enfore:'pre',  
         // 延后执行  
        // enfore:'post',  
       loader: "babel-loader",  
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ],

  mode: 'development'
}

4.2 eslint 配置

ESlint规则文档

4.2.1 安装和初始化

#  1.  下载安装 eslint eslint-webpack-plugin
npm i eslint eslint-webpack-plugin  -D

# 2.  初始化配置 eslint 
# 可以自动初始化一个 eslint 配置文件,也可以 直接自定义一个 eslint配置文件 .eslintrc.js
npm init @eslint/config  # 推荐

# 注意:如果想要 继承 airbnb 规则,安装以下依赖
npm i eslint-config-airbnb-base eslint-plugin-import eslint-import-resolver-webpack  -D
  • off 或 0:关闭对该规则的校验;
  • warn 或 1:启用规则,不满足时抛出警告,且不会退出编译进程;
  • error 或 2:启用规则,不满足时抛出错误,且会退出编译进程;

4.2.2 .eslintrc.js 配置

module.exports = {
  // 继承 Eslint 规则
  extends: ["eslint:recommended"],
    
  // 也可以继承 airbnb规则 
  // extends: ["airbnb-base"],  
    
  // 继承 Vue-cli 官方规则
  // extends: ["plugin:vue/essential"],  
    
  env: {
    node: true, // 启用node中全局变量
    browser: true, // 启用浏览器中全局变量
    es2021: true
  },
  parserOptions: {
    ecmaVersion: 6, // es6
    sourceType: "module", // es module
  },
  rules: {
    "no-var": 2, // 不能使用 var 定义变量
    "semi": 0, // 末尾加分号
    "quotes": 0, // 字符串必须使用单引号
    "linebreak-style": 0 // 不同工具下 换行符问题
  },
  // 可以解决 动态导入语法错误
  plugins: ['import'] 
};

4.2.3 webpack.config.js 配置

配置 eslint-webpack-plugin 插件

  plugins: [
    new HtmlWebpackPlugin(),
    new ESLintPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "src"),
      // 排除 node_modules 中js文件的检查
      exclude: 'node_modules'
    }),
  ],

webpack.config.js 配置文件

const path = require('path')

const HtmlWebpackPlugin = require('html-webpack-plugin');
const ESLintPlugin = require('eslint-webpack-plugin');


module.exports = {
  mode: 'development',

  entry: './src/index.js',

  devtool: 'source-map',

  devServer: {
    static: path.resolve(__dirname, './dist'),
    compress: true,
    port: 5000,
  },
  plugins: [
    new HtmlWebpackPlugin(),
    new ESLintPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "src"),
      // 排除 node_modules 中js文件的检查
      exclude: 'node_modules'
    }),
  ],
};

4.2.4 .eslintignore 忽略配置

一般都会忽略 node_modules 等 文件的eslint 校验

dist
node_modules

4.3 .browserslistrc 目标浏览器的环境 配置

一些常见的配置,例如 postcss,babel 都会共用这个 .browserslistrc 里面的浏览器配置

4.3.1 配置文件 .browserslistrc -推荐

创建一个文件 .browserslistrc

Android 4.1
iOS 7.1
Chrome > 31
ff > 31
ie >= 8

4.3.2 package.json 配置

"browserslist":[
	"1%",
	"last 2 version",
	"not dead"
]

5 webpack之 配置 devServer

5.1 介绍

1、 一个基于expressjs的开发服务器,提供实时刷新浏览器页面的功能,又称 热模块替换(模块热替换)

2、 模块热替换:相当于ajax局部刷新功能,不用刷新浏览器,它是只让修改到的模块,才会在浏览器上发生相应的变化,而不是重新刷新浏览器;

一个模块发生变化,只会重新打包这一个模块,而不是打包所有模块,这样可以极大的提升构建速率

3、 webpack --watch 或 webpack-dev-server 的主要功能可以监听文件改变,只要文件发生变化,就会自动刷新

4、 webpack-dev-server实现热更新(HMR),就是一个基于node.js和webpack的小型服务器

5、 模块热替换功能会在应用程序运行过程中替换、添加或删除模块,无需重新加载整个页面。主要是通过以下几种方式,来显著加快开发速度:

  • 保留在完全重新加载页面时丢失的应用程序状态。
  • 只更新变更内容,以节省宝贵的开发时间。
  • 调整样式更加快速 - 几乎相当于在浏览器调试器中更改样式

6、 可以实现热更新的模块

  • 样式文件:本身就可以使用HMR功能,因为style-loader内部实现了

  • js文件:默认不能使用HMR功能: 需要修改js代码,添加支持HMR功能的代码(只能处理非入口js文件的其他文件)

  • html文件: 默认不能使用HMR功能,同时会导致问题:html文件不能热更新了~ (其实也不用做HMR功能)

    解决方案:修改entry入口,将html文件引入

5.2 安装和配置

npm i webpack-dev-server -D

# 安装webpack-dev-server(在指定目录下),一定要先安装完毕webpack webpack-cli之后在安装webpack-dev-server

webpack.config.js

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'build.js',
    path: resolve(__dirname, 'build'),
    clean: true
  },
  module: {
    rules: [
      // 配置编译css文件的loader
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      {
        test: /\.s[a|c]ss$/i,

        use: [
          'style-loader',
          'css-loader',
          'sass-loader'
        ]
      }
    ]
  },
  // 配置本地服务
  // 开发服务器 devServer:用来自动化(自动编译,自动打开浏览器,自动刷新浏览器~~)
  // 特点:只会在内存中编译打包,不会有任何输出
  // 启动devServer指令为:npx webpack-dev-server
  devServer: {
    // 默认 目录就是 dist 文件夹
    static: resolve(__dirname, './dist'),

    // 启用gzip压缩
    compress: true,

    // 端口号
    port: 3000,

    // 自动打开浏览器
    open: true,

    // 开启 IP 地址访问,开发服务器主机
    host: '0.0.0.0',
      
    hot:true, // 启用HMR功能, 默认就是开启状态  
      
    // 如果想要 写入硬盘,可以做如下配置
    devMiddleware:{
        writeToDisk:true
    }

    // 开启代理(重点)
    proxy: {
      '/api': {
        // target如果是域名,changeOrigin必须开启为 true
        target: 'http://www.baidu.com',
        changeOrigin: true,

        /** 路径重写
         *  比如访问的API路径:/api/store/get,设置了路径重写功能以后,那么最后的访问地址就会是:http://www.baidu.com/store/get
         */
        pathRewrite: {
          '^/api': ''
        },
      },
    },

    // 设置响应头
    headers: {
      'X-Access-Token': 'abc123'
    },

    // http2默认自带https自签名证书,可以访问 https 协议
    http2: true,

    // 防止 当页面应用 报错
    historyApiFallback: true

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

运行

# 运行命令
npx webpack serve

# 或者 配置 npm运行命令 ,然后运行 npm run serve
 "scripts": {
    "serve": "webpack serve"
  },

代理 proxy 参数

/api

捕获API的标志,如果API中有这个字符串,那么就开始匹配代理,比如API请求/api/store/get, 会被代理到请求 http://www.baidu.com/api/store/get

target

代理的API地址,就是需要跨域的API地址。

地址可以是域名:如:http://www.baidu.com

也可以是IP地址:http://127.0.0.1:3000

如果是域名需要额外添加一个参数 changeOrigin: true ,否则会代理失败。

pathRewrite

路径重写,也就是说会修改最终请求的API路径

比如访问的API路径:/api/store/get , 设置 pathRewrite: {'^/api' : ''} 后,最终代理访问的路径:http://www.baidu.com/store/get ,这个参数的目的是给代理命名后,在访问时把命名删除掉。

changeOrigin

这个参数可以让target参数是域名。

secure

secure: false,不检查安全问题。

设置后,可以接受运行在 HTTPS 上,可以使用无效证书的后端服务器