webpack常用依赖

webpack 官方examples

hash、chunkhash、contenthash 的区别:

hash
是编译过程根据整个项目产生的一个总的 hash 值,而不是单个文件的 hash 值,项目中任何一个文件的改动,都会造成这个 hash 值的改变。简单点说就是: **每次build,项目代码没有任何改变,编译出来的 hash不变;代码有任何改变,hash就会发生改变。**

chunkhash
chunkhash是根据具体每一个模块文件的的内容包括它的依赖计算出来的hash,所以某个文件的改动只会影响它本身的hash,不会影响其它文件。

contenthash
它的出现主要是为了解决,让css文件不受js文件的影响。比如foo.css被foo.js引用了,所以它们共用相同的chunkhash值。但这样子是有问题的,如果foo.js修改了代码,css文件内容没有任何改变,由于是该模块的 hash 发生了改变,其css文件的hash也会随之改变。
这个时候我们就可以使用contenthash了,保证即使css文件所处的模块里有任何内容的改变,只要 css 文件内容不变,那么它的hash就不会发生变化。

CSS 相关
webpack官方文档
style-loader能将css以style的形式插入 , css-loader 能够使用@import 和 url(…)的方法实现 require()的功能
预处理器 sass less stylus 选熟悉的、
postcss 提供了 autoprefixer 自动添加css前缀,也是很有必要的。
Mini-CSS 插件 提取css到单独文件

yarn add style-loader css-loader less-loader less -D
yarn add postcss-loader autoprefixer -D
yarn add mini-css-extract-plugin --dev

创建 postcss.config.js,并粘贴以下内容:

module.exports = {
    plugins: [
      require('autoprefixer')
    ]
}

webpack配置

// webpack v4
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== 'production'
module.exports = {
  //...
  module: {
    rules: [
      //...
      {
        test: /\.(le|c)ss$/,
        // 注意顺序
        use:  [  devMode ? 'style-loader' : MiniCssExtractPlugin.loader, 'css-loader','postcss-loader','less-loader']
      }
    ]
  },
  plugins: [
    //...
    new MiniCssExtractPlugin({
      // filename 是指在你入口文件entry中引入生成出来的文件名
      // chunkname是指那些未在入口文件entry引入,但又通过按需加载(异步)模块的时候引入的文件。
      filename: devMode ? '[name].css' : '[name].[contenthash].css',
      chunkFilename: devMode ? '[id].css' : '[id].[contenthash].css',
    })
    //...
  ]
};

HTML处理
根据模板动态生成index.html(webpack打包后的文件名实际项目中一般是动态生成的,index.html中需要引入它们)。webpack官方文档
安装
yarn add html-webpack-plugin --dev

配置

// webpack v4
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  //...
  module: {
    rules: [...]
  },
  plugins: [ 
    //...
    new HtmlWebpackPlugin({
      inject: false,
      hash: true,
      //模板index.html文件head中<title><%=htmlWebpackPlugin.options.title%></title>
      // 生成的index.html文件head中<title>这是啥</title>
      title   : "这是啥",
      template: './src/index.html', // 模板文件
      filename: 'index.html' //生成文件名
    })
    //...
  ]
};

清除 dist 目录
每次打包清除 dist 目录的文件(之前打包生成的),然后重新把打包生成的文件放进去
安装
yarn add clean-webpack-plugin -D

配置

const CleanWebpackPlugin = require("clean-webpack-plugin");		//重置打包文件夹

module.exports = {
    //...
    plugins: [
    	//...
        new CleanWebpackPlugin("./dist"),   //重置打包文件夹
        //...
    ],
    //...
}

静态资源处理

在 webpack配置里添加
npm install --save-dev url-loader file-loader


// webpack.config.js -> rules增加配置:
{
   test: /\.(png|jpg|gif)$/,
   use: [{
       loader: 'url-loader',
       options: {
           limit: 8192  //8k一下的转义为base64
       }
   }]
}

babel转码
yarn add babel-loader @babel/core @babel/preset-env @babel/runtime @babel/plugin-transform-runtime -D

修改配置文件

{
    test: /\.js$/,
    exclude: /(node_modules)/,
    use: {
        loader: 'babel-loader?cacheDirectory', // 通过cacheDirectory选项开启支持缓存
        options: {
          presets: ['@babel/preset-env']
        }
    }
}

增加babel.config.js配置文件

// 仅供参考
module.exports = {
    "presets": [
      [
        "@babel/preset-env"
      ]
    ],
    "plugins": [
      [
        "@babel/plugin-transform-runtime",
        {
          "corejs": false,
          "helpers": true,
          "regenerator": true,
          "useESModules": false,
          "absoluteRuntime": "@babel/runtime"
        }
      ]
    ]
  }

语法报错和代码规范检查
参考文章

yarn eslint eslint-loader -D
// 校验规则
yarn babel-eslint standard -D

修改webpack配置文件

  {
    test: /\.js$/,
    exclude: /(node_modules|bower_components)/,
    use: [
      {
        loader: 'babel-loader?cacheDirectory', // 通过cacheDirectory选项开启支持缓存
        options: {
          presets: ['@babel/preset-env']
        }
      },
      {
        loader: 'eslint-loader',
        options: {
          fix: true
        }
      }
    ]
  },

增加.eslintrc.js文件

/*
 * ESLint的JSON文件是允许JavaScript注释的,但在gist里显示效果不好,所以我把.json文件后缀改为了.js
 */

/*
 * ESLint 配置文件优先级:
 * .eslintrc.js(输出一个配置对象)
 * .eslintrc.yaml
 * .eslintrc.yml
 * .eslintrc.json(ESLint的JSON文件允许JavaScript风格的注释)
 * .eslintrc(可以是JSON也可以是YAML)
 *  package.json(在package.json里创建一个eslintConfig属性,在那里定义你的配置)
 */

/*
 * 你可以通过在项目根目录创建一个.eslintignore文件告诉ESLint去忽略特定的文件和目录
 * .eslintignore文件是一个纯文本文件,其中的每一行都是一个glob模式表明哪些路径应该忽略检测
 */

module.exports = {
  //ESLint默认使用Espree作为其解析器
  //同时babel-eslint也是用得最多的解析器
  //parser解析代码时的参数
  "parser": "babel-eslint",
  "parserOptions": {
    //指定要使用的ECMAScript版本,默认值5
    "ecmaVersion": 6
    //设置为script(默认)或module(如果你的代码是ECMAScript模块)
    // "sourceType": "script",
    //这是个对象,表示你想使用的额外的语言特性,所有选项默认都是false
    // "ecmafeatures": {
    //   //允许在全局作用域下使用return语句
    //   "globalReturn": false,
    //   //启用全局strict模式(严格模式)
    //   "impliedStrict": false,
    //   //启用JSX
    //   "jsx": false,
    //   //启用对实验性的objectRest/spreadProperties的支持
    //   "experimentalObjectRestSpread": false
    // }
  },
  //指定环境,每个环境都有自己预定义的全局变量,可以同时指定多个环境,不矛盾
  "env": {
    //效果同配置项ecmaVersion一样
    "es6": true,
    "browser": true,
    "node": true,
    "commonjs": false,
    "mocha": true,
    "jquery": true,
    //如果你想使用来自某个插件的环境时,确保在plugins数组里指定插件名
    //格式为:插件名/环境名称(插件名不带前缀)
    // "react/node": true
  },

  //指定环境为我们提供了预置的全局变量
  //对于那些我们自定义的全局变量,可以用globals指定
  //设置每个变量等于true允许变量被重写,或false不允许被重写
  "globals": {
    "globalVar1": true,
    "globalVar2": false
  },

  //ESLint支持使用第三方插件
  //在使用插件之前,你必须使用npm安装它
  //全局安装的ESLint只能使用全局安装的插件
  //本地安装的ESLint不仅可以使用本地安装的插件还可以使用全局安装的插件
  //plugin与extend的区别:extend提供的是eslint现有规则的一系列预设
  //而plugin则提供了除预设之外的自定义规则,当你在eslint的规则里找不到合适的的时候
  //就可以借用插件来实现了
  "plugins": [
    // "eslint-plugin-airbnb",
    //插件名称可以省略eslint-plugin-前缀
    // "react"
  ],

  //具体规则配置
  //off或0--关闭规则
  //warn或1--开启规则,警告级别(不会导致程序退出)
  //error或2--开启规则,错误级别(当被触发的时候,程序会退出)
  "rules": {
    "eqeqeq": "warn",
    //你也可以使用对应的数字定义规则严重程度
    "curly": 2,
    //如果某条规则有额外的选项,你可以使用数组字面量指定它们
    //选项可以是字符串,也可以是对象
    "quotes": ["error", "double"],
    "one-var": ["error", {
      "var": "always",
      "let": "never",
      "const": "never"
    }],
    //配置插件提供的自定义规则的时候,格式为:不带前缀插件名/规则ID
    // "react/curly": "error"
  },

  //ESLint支持在配置文件添加共享设置
  //你可以添加settings对象到配置文件,它将提供给每一个将被执行的规则
  //如果你想添加的自定义规则而且使它们可以访问到相同的信息,这将会很有用,并且很容易配置
  "settings": {
    "sharedData": "Hello"
  },

  //Eslint检测配置文件步骤:
  //1.在要检测的文件同一目录里寻找.eslintrc.*和package.json
  //2.紧接着在父级目录里寻找,一直到文件系统的根目录
  //3.如果在前两步发现有root:true的配置,停止在父级目录中寻找.eslintrc
  //4.如果以上步骤都没有找到,则回退到用户主目录~/.eslintrc中自定义的默认配置
  "root": true,

  //extends属性值可以是一个字符串或字符串数组
  //数组中每个配置项继承它前面的配置
  //可选的配置项如下
  //1.字符串eslint:recommended,该配置项启用一系列核心规则,这些规则报告一些常见问题,即在(规则页面)中打勾的规则
  //2.一个可以输出配置对象的可共享配置包,如eslint-config-standard
    //可共享配置包是一个导出配置对象的简单的npm包,包名称以eslint-config-开头,使用前要安装
    //extends属性值可以省略包名的前缀eslint-config-
  //3.一个输出配置规则的插件包,如eslint-plugin-react
    //一些插件也可以输出一个或多个命名的配置
    //extends属性值为,plugin:包名/配置名称
  //4.一个指向配置文件的相对路径或绝对路径
  //5.字符串eslint:all,启用当前安装的ESLint中所有的核心规则
    //该配置不推荐在产品中使用,因为它随着ESLint版本进行更改。使用的话,请自己承担风险
  "extends": [
    "standard"
  ]
}

增加.eslintignore文件

/dist/
/node_modules/
/*.js

webpack配置resolve模块解析
配置alias方便路径的检索效率。
配置文件默认扩展名,import时候自动匹配。

resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      '@': path.resolve(__dirname, 'src/')
    }
},

webpack配置外部扩展externals
externals选项可以提供排除打包某些依赖到boundle的方法.例如我们想通过CDN引入jQuery而不是把jQuery打包到bundle。

修改配置文件

// 配置外部依赖不会打包到boudle
externals: {
    jquery: 'jQuery'
},

在模板文件引入CDN

// index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="google" value="notranslate">
    <meta http-equiv="Cache-Control" content="no-siteapp">
    <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
    <meta name="format-detection" content="telephone=no">
    <script
    src="https://code.jquery.com/jquery-3.3.1.js"
    integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
    crossorigin="anonymous"></script>
    <title><%= htmlWebpackPlugin.options.title %></title>
</head>

<body>
    <div id="app"></div>
    <div class="logo"></div>
    <div class="man"></div>
</body>
</html>

在index.js使用jquery

import $ from 'jquery'

// 测试外部扩展配置
$(function () {
  $('.logo').click(function () {
    console.log('click')
  })
})

提取公共js

在 webpack配置 里添加

output: {
    ...
    chunkFilename: '[name].[chunkhash:8].js'
},
...
optimization: {
    splitChunks: {
        cacheGroups: {
            vendor: {
                test: /[\\/]node_modules[\\/]/,
                name: 'common',
                chunks: 'all'
            }
        }
    }
},

本地服务器
开发时运行在本地服务器上的,修改代码自动刷新,这才是正常操作。所以,需要用到webpack-dev-server。

yarn add webpack-dev-server -D

webpack中配置devServer官方文档

常用配置选项如下:

contentBase :设置服务器所读取文件的目录,当前我们设置为"./dist"
headers:在所有响应中添加首部内容
port :设置端口号,如果省略,默认为8080
hot :启用 webpack 的模块热替换特性(自动刷新变化的部分) ,需要配合webpack内置的 HMR 插件 使用
inline :设置为true,当源文件改变时会自动刷新页面 (--inline --hot 优先重新加载改变的部分,失败则刷新页面)
historyApiFallback :设置为true,任意的404响应都跳转将到index.html //与output的publicPath有关(HTMLplugin生成的html默认为index.html)

source map 方便调试
当 webpack 打包源代码到一个 bundle(bundle.js)中,调试代码时,没办法追踪到错误和警告在源代码中的原始位置。这时候,会不会感觉人生好艰难。
为了更容易地追踪错误和警告,webpack提供了 source map 功能,将编译后的代码映射回原始源代码。如果一个错误来自于 b.js,source map在浏览器的调试工具中会提示错误出现在源码的位置。

webpack的配置文件中配置source maps,需要配置devtool,它有以下四种不同的配置选项,各具优缺点,描述如下:

devtool选项配置结果
source-map在一个单独的文件中产生一个完整且功能完全的文件。这个文件具有最好的source map,但是它会减慢打包速度;
cheap-module-source-map在一个单独的文件中生成一个不带列映射的map,不带列映射提高了打包速度,但是也使得浏览器开发者工具只能对应到具体的行,不能对应到具体的列(符号),会对调试造成不便;
eval-source-map使用eval打包源文件模块,在同一个文件中生成干净的完整的source map。这个选项可以在不影响构建速度的前提下生成完整的sourcemap,但是对打包后输出的JS文件的执行具有性能和安全的隐患。在开发阶段这是一个非常好的选项,在生产阶段则一定不要启用这个选项;
cheap-module-eval-source-map这是在打包文件时最快的生成source map的方法,生成的Source Map 会和打包后的JavaScript文件同行显示,没有列映射,和eval-source-map选项具有相似的缺点;

正如上表所述,上述选项由上到下打包速度越来越快,不过同时也具有越来越多的负面作用,较快的打包速度的后果就是对打包后的文件的的执行有一定影响。

使用CDN引入资源
以echarts为例,操作步骤如下:

在index.html中引入echarts的CDN资源

在webpack.base.config.js中配置externals选项,externals与entry平级。

externals: {
“echarts”: “echarts”
}

externals中的key是给import的时候用的,value表示的是如何在global中访问到该对象,这里是window.echarts;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值