美文网首页让前端飞Web前端之路
webpack使用与配置(下)

webpack使用与配置(下)

作者: XJBT | 来源:发表于2019-06-18 12:56 被阅读0次

    对于之前webpack使用与配置(上)
    的补充

    1. 使用typescript时需要在根目录下创建一个tsconfig.js的文件

    2. 关于.babelrc的配置

      • 直接在webpack.config.js中配置options
      • 创建.babelrc文件,在该文件中配置
      • 注意二者取其一就行了,当然也可以两者互补,只要两者合并起来能满足配置需求即可

      webpack.config.js中的配置是这样的:

          {
              test: /\.js$/, // normal 普通的 loader
              use: {
                  loader: 'babel-loader',
                  options: { // 用babel-loader 需要把 es6 -> es5
                      presets: [
                          '@babel/preset-env',
                          '@babel/preset-react'
                      ],
                      plugins: [
                          ["@babel/plugin-proposal-decorators", { "legacy": true }], // 装饰器语法
                          ["@babel/plugin-proposal-class-properties", { "loose": true }], // 支持 class 语法
                          "@babel/plugin-transform-runtime", // 运行时,支持 promise 或 gen*
                          "@babel/plugin-syntax-dynamic-import", // 支持 import then 语法
                      ]
                  }
              },
              include: path.resolve(__dirname, '../src'), // 指定为 src 文件
              exclude: /node_modules/, // 排除 node_modules
          }
      

      .babelrc中的配置是这样的:

          {
              presets: [
                  '@babel/preset-env',
                  '@babel/preset-react'
                  // 使用react必须配置的presets项
              ],
              plugins: [
                  ["@babel/plugin-proposal-decorators", { "legacy": true }], // 装饰器语法
                  ["@babel/plugin-proposal-class-properties", { "loose": true }], // 支持 class 语法
                  "@babel/plugin-transform-runtime", // 运行时,支持 promise 或 gen*
                  "@babel/plugin-syntax-dynamic-import", // 支持 import then 语法
              ]
          }
      

      终于可以摆脱脚手架了。。。。。*(幼稚的想法)

    3. hashchunkhashcontenthash的配置

      • hash 计算是跟整个项目的构建相关,也就是说如果配置的是hash,那么只要项目中一个文件发生变化,那么所有的hash都会发生变化,这对缓存来说是一种浪费,使用hash时所有的hash值都是一样的,发生变化时一起变化
      • chunkhash 就是解决上面这个问题的,它根据不同的入口文件(Entry)进行依赖文件解析、构建对应的 chunk,生成对应的哈希值。即一个chunk里面修改的内容不会影响到另一个chunk,只有自己这个chunkchunkhash会发生变化
        • 我们更近一步,index.jsindex.css 同为一个 chunkindex.css是同一个chunk里面抽出来的),如果 index.js 内容发生变化,但是 index.css 没有变化,打包后他们的 hash 都发生变化,这对 css 文件来说是一种浪费。如何解决这个问题呢?contenthash 将根据资源内容创建出唯一 hash,也就是说文件内容不变,hash 就不变。
    4. mini-css-extract-plugin的使用姿势:

      • 先是装包,在plugins里面new出来一个实例
          new MiniCssExtractPlugin({
              filename: 'index.[contenthash:8].css'
              // 使用contenthash的好处见上一条
          }),
      
      • 修改rules里面的配置,现在不是用style-loader了,而是要利用mini-css-extract-plugin提供的loader
          {
              test: /\.scss$/,
              use: [
                  // 这里替换了原来的style-loader
                  { 
                      loader: MiniCssExtractPlugin.loader,
                      options: {
                          hmr: true,
                          reloadAll: true
                      }
                  }, 
                  {
                      loader: 'css-loader',
                      options: {
                          modules: true
                      }
                  }, 
              'sass-loader', 'postcss-loader'],
          }
      

      如果不抽离css文件那么所有的css样式内容都会在打包后被放在bundle.js文件中,造成的结果就是bundle.js文件内容过大,如果是一个单页应用的话,需要花更多的时间去下载bundle.js,首屏体验就不好,抽离css文件的作用应该就是这个,将css样式的内容抽离出css文件,通过link标签引入index.html中,这样在下载css内容的时候可以继续构建DOM树也可以继续下载后面的bundle.js,阻塞的只是DOM的渲染和bundle.js的执行,总体来说是提升了性能的。

    5. optimize-css-assets-webpack-plugin
      这个插件用于对css资源进行压缩,食用方式是在optimization里面进行配置

          const OptimizeCss = require('optimize-css-assets-webpack-plugin')
          const Uglify = require('uglifyjs-webpack-plugin')
      
          mode: 'production',
          optimization: {
              minimizer: [
                  new OptimizeCss(),
                  new Uglify(),
              ],
          },
      

      注意:虽然mode已经设置为production,但是使用了optimize-css-assets-webpack-plugin插件之后如果不使用uglifyjs插件的话js文件将无法压缩,展现出来的是和development模式是一样的,当然如果设置的是development模式的话,即使使用了uglifyjs插件也无法压缩。

    6. externals配置
      譬如通过<script></script>标签引入了jQueryCDN,此时在文件中使用$或者window.$都可以直接使用jQuery,也不需打包进bundle.js,但是如果此时又写了import $ from 'jquery'(纯属为了看着顺眼);的话,jQuery又会被打包进bundle.js,为了避免这样的情况(不用引入的情况偏偏引入了,又不想打包),可以通过配置externals属性来忽略一些不需要打包的内容

          externals: {
              jquery: '$',
          }
      
    7. 在处理图片时,有三种情况

      • js文件中创建img,然后添加进DOM tree
            import imgSrc from './a.jpg';
            const image = new Image()
            image.src = imgSrc
        
      • css文件中作为background使用
        {
            backgroung: url('./a.jpg');
            // 此时不需要先引入,是因为css-loader已经做了这一步操作
        }
        
      • html文件中直接使用
            <img src='./a.jpg' />
        
        为了将该src转化为图片打包后的地址,使用一个loaderhtml-withimg-loader
            {
                test: /\.html$/,
                loader: 'html-withimg-loader'
            }
        

      注意:在配置webpack.config.js时可以像下面这样配置,但是虽然我们只使用了url-loader,但是需要同时装包file-loader,因为由于limit的限制,当图片文件大于200K时会使用file-loader打包出一个图片文件放在build文件夹下,图片大小小于limit限制时是以base64的形式打包进bundle.js文件,也就是说url-loader里面可能会使用到file-loader,这样做的目的也是为了防止bundle.js文件过大,另一个原因是图片过大时编码需要的时间较长,影响打包的速度。但是如果图片较多,会发很多 http 请求,会降低页面性能,所以当图片体积较小时 url-loader 会将引入的图片编码,转为 base64 字符串。再把这串字符打包到文件中,最终只需要引入这个文件就能访问图片了,节省了图片请求。

      ```
          {
              test: /\.(jpg|png|gif)$/,
              use: {
                  loader: 'url-loader',
                  options: {
                      limit: 200*1024,
                      outputPath: 'img/'
                      // 会在build目录下创建一个img目录
                  }
              }
          },
      ```
      
    8. 关于publicPath的配置,这是代码上线后将资源托管在CDN服务器上,此时html文件中引入各个bundle.js文件不再是本地引入,而是要去CDN服务器上引入,如果继续写成./bundle.js就无法获取到资源,所以就要给所有的引入路径添加上一个公共的路径,譬如说放在http://www.navyblue.com/CDN服务器上,那么publicPath就设置为http://www.navyblue.com/,这时候在html引入bundle.js的时候就会自动去引入http://www.navyblue.com/bundle.js。如果在output中配置publicPath那么打包出来的所有结果被引入时都会加上公共路径,如果想单独配置,譬如说只给图片加,那么就可以在url-loaderoptions里面配置
      { test: /\.(jpg|png|gif)$/, use: { loader: 'url-loader', options: { limit: 200*1024, outputPath: 'img/', // 会在build目录下创建一个img目录 publicPath: 'http://www.navyblue.com/' } } },

    9. 关于chunkbundlemodule的区别:

      • module好理解,就是需要被打包的一个个模块
      • bundle就是打包出来的一个个js文件
      • chunk:一个entrypoint进去以后,根据各种依赖关系形成一大个chunk,如果在打包一个chunk的过程中需要分割代码,那么分割完最后得到的一个个包就是bundle
    10. 关于html-webpack-plugin的使用: 对于多页应用需要new多个plugin出来

          new HtmlWebpackPlugin({
              template: './src/index.html',
              minify: {
                  removeAttributeQuotes: true,
              },
              filename: 'home.html',
              // filename是打包结束后输出的html文件名
              chunks: ['main'],
              // chunks是指该html需要引入的js文件,里面的`main`其实就是一个entrypoint,因为一个entrypoint对应的就是一个chunk
          }),
          new HtmlWebpackPlugin({
              template: './src/index.html',
              minify: {
                  removeAttributeQuotes: true,
              },
              filename: 'other.html',
              chunks: ['sub'],
          }),
      
    11. resolve的配置:

          resolve: { //  解析模块的可选项
              modules: [ // 模块的查找目录
                  "node_modules",
                  path.resolve(__dirname, "app")
              ],
              extensions: [".js", ".json", ".jsx", ".css"], // 用到的文件的扩展
              alias: { // 模块别名列表
                  "module": "new-module"
                  // 用到的别名:真正的路径
              },
          },
      
    12. production mode(生产模式) 可以开箱即用地进行各种优化。 包括压缩,作用域提升,tree-shaking 等。

    13. 对于cacheGroups的配置:

          splitChunks: {
              chunks: 'all',
              minSize: 50000,
              minChunks: 2,
              // 内部的minChunks可以覆盖这里的minChunks
              cacheGroups: {
                  lodash: {
                      name: 'mylodash',
                      test: /[\\/]node_modules[\\/]lodash/,
                      // 选择匹配的模块
                      // 譬如第一个包打包的只有lodash,因为没匹配到react所以不会分割到这个包里
                      minChunks: 1,
                      priority: 10,
                      // 打包会根据priority的大小从大到小打包
                  },
                  react: {
                      name: 'myreact',
                      test: /[\\/]node_modules[\\/]react/,
                      minChunks: 1,
                      priority: 5,
                  },
                  vendors: {
                      name: 'myGroups',
                      test: /[\\/]node_modules1[\\/]/,
                      priority: -10,
                      minChunks: 1,
                  },
                  default: {
                      name: 'default',
                      // 默认有个default配置,但是如果显示写出来又全都没匹配中的话会再次调用一个隐式的default
                      minChunks: 1,
                      priority: -20,
                  }
              }
          },
      
    14. @babel/polyfill

    Babel默认只转换新的JavaScript句法(syntax),而不转换新的API,比如IteratorGeneratorSetMapProxyReflectSymbolPromise等全局对象,以及一些定义在全局对象上的方法(比如Object.assign)都不会转码。

    举例来说,ES6Array对象上新增了Array.from方法。Babel就不会转码这个方法。如果想让这个方法运行,必须使用@babel-polyfill,为当前环境提供一个垫片,使得在当前环境下可以执行该方法。

    1. 关于CSS代码

    css-loader:负责解析 CSS 代码,主要是为了处理 CSS 中的依赖,例如 @importurl() 等引用外部文件的声明

    style-loader 会将 css-loader 解析的结果转变成 JS 代码,运行时动态插入 style 标签来让 CSS 代码生效。

    相关文章

      网友评论

        本文标题:webpack使用与配置(下)

        本文链接:https://www.haomeiwen.com/subject/jgxfqctx.html