vue-11-cli3 vue.config.js 文件配置

由于vue-cli3及以上版本将webpack的基础配置全部内嵌了,这就导致我们初始化项目完成之后发现原先的webpack的config配置全部都消失不见了,vue-cli3预留了一个 vue.config.js 的js文件供我们对webpack进行自定义配置,参考 vue.config.js官方配置指南

转载一篇 有关于 webpack 配置的 文章 https://presentations.survivejs.com/webpack-the-good-parts/#/3

1、在项目根目录下新建 vue.config.js 文件与package.json同级

这个文件应该导出一个包含了选项的对象:

// vue.config.js
module.exports = {
  // 选项...
}

 以下是在配置 vue.config.js  文件时,常用的属性

#publicPath

baseUrl -- publicPath -- 从 Vue CLI 3.3 起已弃用,请使用publicPath

// vue.config.js
module.exports = {
  /* 部署生产环境和开发环境下的项目路径:可对当前环境进行区分,baseUrl 从 Vue CLI 3.3 起已弃用,要使用publicPath */ 
  /* 如果是部署在根路径,那么可以直接使用 默认值 ‘/’ ,也可以被设置为空字符串 ('') 或是相对路径 ('./'),这样所有的资源都会被链接为相对路径,这样打出来的包可以被部署在任意路径 */
  /* baseUrl: process.env.NODE_ENV === 'production' ? '/' : './' */
    publicPath: process.env.NODE_ENV === 'production' ? '' : './',
  /* 默认情况下,Vue CLI 会假设你的应用是被部署在一个域名的根路径上,例如 https://www.my-app.com/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.my-app.com/public/,则设置 publicPath 为 /public/。 */
    publicPath: process.env.NODE_ENV === 'production' ? '/public/' : '/',
}

#outputDir 

// vue.config.js
module.exports = {
  /* 输出文件目录:在npm run build时,生成文件的目录名称 默认是dist */
  /* 当我在build 时,若是区分了不同环境,那么我可能会需要针对不同环境的 build ,需要一个不同的包名 */
  /* 如果build 的是测试环境,也就是运行的是 "build:test": "vue-cli-service build --mode test" 这个脚本命令 ,那么我希望我的包名是 dist_test*/
  /* 那么我可以在 .env.test 这个环境模式中,增加一个变量,用来定义不同环境下的包名,然后 使用这个变量来定义输出的包名 */
  outputDir: process.env.OUT_PUT_DIR,
}



//  .env.test 模式
NODE_ENV = 'test'
VUE_APP_TITLE = '2'
OUT_PUT_DIR = dist_test  //包名变量

#assetsDir 

// vue.config.js
module.exports = {
  /* 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录 */
  /* 一般会将这些静态文件,放置在 src 文件夹下的 assets 文件夹下 */
    assetsDir: "assets",
}

#pages 

每个“page”应该有一个对应的 JavaScript 入口文件。其值应该是一个对象,

1、对象的 key 是入口的名字,也就是 index 。

2、value 存在两种情况

  • 一个指定了 entrytemplatefilenametitle 和 chunks 的对象 (除了 entry 之外都是可选的);
  • 或一个指定其 entry 的字符串

通常情况下,value只指定了 entrytemplatefilename 这三个属性

// vue.config.js
module.exports = {
  pages: {
    index: {
      // page 的入口 ,其实也就是 main.js 文件的路径
      entry: 'src/index/main.js',
      // 模板来源 ,就是public文件夹中 index.html 文件的路径
      template: 'public/index.html',
      // 在 dist/index.html 的输出,打包之后的文件夹中,index.html 文件的路径
      filename: 'index.html',
      // 当使用 title 选项时,
      // template 中的 title 标签需要是 <%= htmlWebpackPlugin.options.title %>
      title: 'Index Page',
      // 在这个页面中包含的块,默认情况下会包含
      // 提取出来的通用 chunk 和 vendor chunk。
      chunks: ['chunk-vendors', 'chunk-common', 'index']
    },
    // 当使用只有入口的字符串格式时,
    // 模板会被推导为 `public/subpage.html`
    // 并且如果找不到的话,就回退到 `public/index.html`。
    // 输出文件名会被推导为 `subpage.html`。
    subpage: 'src/subpage/main.js'
  }
}

 #lintOnSave

在编译时,通过eslint-loader  来 lint 代码。

设置为 true 或者 'waring' 会将 lint 错误输出为编译警告。默认情况下,警告仅仅会被输出到命令行,且不会使得编译失败。

设置为 'error' 会强制将 lint 错误输出为编译错误,同时也意味着 lint 错误将会导致编译失败。

如果需要在生产环境构建时禁用,以免编译失败,可以采用以下配置

// vue.config.js
module.exports = {
  lintOnSave: process.env.NODE_ENV !== "production" ? true : "warning",
}

 #productionSourceMap

如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。但是一般我都是不区分环境,直接 false

有关于 source map:可以参考这篇文章 sourceMap是个啥

// vue.config.js
module.exports = {
  productionSourceMap: false,
}

#configureWebpack 

调整 webpack 配置最简单的方式就是在 vue.config.js 中的 configureWebpack 选项提供一个对象:该对象将会被 webpack-merge 合并入最终的 webpack 配置。

module.exports = {
  configureWebpack: {
    plugins: [
      new MyAwesomeWebpackPlugin()
    ]
  }
}

 如果这个值是一个函数,则会接收被解析的配置作为参数。该函数既可以修改配置并不返回任何东西,也可以返回一个被克隆或合并过的配置版本。

修改配置并不返回任何东西:添加插件的时候需要使用 config.plugins.push() 

// 内部配置,是基于项目需求
configureWebpack: (config) => {
    // 以在浏览器开发工具的性能/时间线面板中启用对组件初始化、编译、渲染和打点
    config.performance = {
      hints:'warning',
      //入口起点的最大体积 整数类型(以字节为单位)
      maxEntrypointSize: 50000000,
      //生成文件的最大体积 整数类型(以字节为单位 300k)
      maxAssetSize: 30000000,
      //只给出 js 文件的性能提示
      assetFilter: function(assetFilename) {
        return assetFilename.endsWith('.js');
      }
    }

    // 修改配置,添加插件
    config.plugins.push(
      
      // 自动加载模块,而不必到处 import 或 require ,在这里加载模块之后,组件内部就不用inport引入了
      new webpack.ProvidePlugin({
        echarts: "echarts"
      }),

      // 扩展环境变量
      new webpack.DefinePlugin({
        APPTYPE: JSON.stringify(env),
        RULEENV: JSON.stringify(process.env.RULE_TYPE),
        PROTYPE: JSON.stringify(process.env.PRODUCTION_TYPE)
      }),


      // HTML文件的配置插件
      new HtmlWebpackPlugin({
        filename: "index.html",
        template: "./public/index.html",
        cdn: cdn,
        minify: {
          removeComments: true, // 移除HTML中的注释
          collapseWhitespace: true, // 删除空白符与换行符
          minifyCSS: true // 压缩内联css
        }
      })
    ),

    
    // 防止将某些 import 的包打包,而是在运行时再去从外部获取这些扩展依赖
    // 比如 我的vue现在是通过cdn引入的,我不希望在打包的时候,将vue打包进去,而是通过cdn调用vue
    (config.externals = {
      vue: "Vue",
      vuex: "Vuex",
      "vue-router": "VueRouter",
      "element-ui": "ELEMENT"
    });

    
    // 针对不同环境进行 配置
    if(isProduction) {

      // 配置插件
      config.plugins.push(
        // new swPlugin('oem' + newversion),
        new GenerateSW({
          cacheId: 'pro-cache',
          skipWaiting: true, //跳过waiting状态
          clientsClaim: true, //通知让新的sw立即在页面上取得控制权
          cleanupOutdatedCaches: true,//删除过时、老版本的缓存
          include: [
          ],
          //缓存规则,可用正则匹配请求,进行缓存
          //这里将js、css、还有图片资源分开缓存,可以区分缓存时间(虽然这里没做区分。。)
          runtimeCaching: [
            {
              urlPattern: /.*\.js$/i,
              handler: 'CacheFirst',
              options: {
                cacheName: 'rys-js',
                expiration: {
                  maxEntries: 30,  //最多缓存20个,超过的按照LRU原则删除
                  maxAgeSeconds: 30 * 24 * 60 * 60, // 30 days
                },
              },
            },
            {
              urlPattern: /.*css.*/,
              handler: 'CacheFirst',
              options: {
                cacheName: 'rys-css',
                expiration: {
                  maxEntries: 30,  //最多缓存30个,超过的按照LRU原则删除
                  maxAgeSeconds: 30 * 24 * 60 * 60, // 30 days
                },
              },
            }
          ]
        }),
        new CompressionWebpackPlugin({
          filename: "[path].gz[query]",
          algorithm: "gzip",
          test: new RegExp("\\.(" + ["js", "css"].join("|") + ")$"), // 匹配文件名
          threshold: 10240, // 对10K以上的数据进行压缩
          minRatio: 0.8,
          deleteOriginalAssets: false // 是否删除源文件
        }),
        
        // 压缩代码,去除 生产环境的 console 和 debugger
        new UglifyJsPlugin({
          uglifyOptions: {
              compress: {
                dead_code: true,
                // warnings: false,
                drop_debugger: true,
                drop_console: true,
              },
          },
          sourceMap: false,
          parallel: true,
        })
      )
    }
  },

返回一个被克隆或合并过的配置版本 : 添加插件的时候,可以直接使用 plugins :[]

// 将某些配置抽离出来,形成公共配置,直接引用
const productionGzipExtensions = ["js", "css"]

// 防止将某些 import 的包打包,而是在运行时再去从外部获取这些扩展依赖
// 比如 我的vue现在是通过cdn引入的,我不希望在打包的时候,将vue打包进去,而是通过cdn调用vue
const externals = {
  vue: "Vue",
  vuex: "Vuex",
  "vue-router": "VueRouter",
  "element-ui": "ElementUI"
}

// 配置插件,可以放置多个插件,以数组形式存储,通过数组扩展运算符展开调用
const commonPlugin = [
  // 扩展环境变量
  new webpack.DefinePlugin({
    BASE_URL: JSON.stringify(process.env.BASE_URL),
    APP_TYPE: JSON.stringify(process.env.APP_TYPE),
    BASE_URL_XZ: JSON.stringify(process.env.BASE_URL_XZ)
  })
]

configureWebpack: () => {
    // 区分环境进行配置
    if (process.env.NODE_ENV === "production") {
      // 返回一个合并后的配置对象
      return {
        // 配置插件
        plugins: [
          // 调用外部配置
          ...commonPlugin,
          new CompressionPlugin({
            filename: "[path].gz[query]",
            algorithm: "gzip",
            test: new RegExp("\\.(" + productionGzipExtensions.join("|") + ")$"), // 匹配文件名
            threshold: 10240, // 对10K以上的数据进行压缩
            minRatio: 0.8,
            deleteOriginalAssets: false // 是否删除源文件
          })
        ],
        externals
      }
    } else {
      return {
        plugins: commonPlugin,
        externals
      }
    }
  },

#chainWebpack 

是一个函数,会接收一个基于 webpack-chain 的 ChainableConfig 实例。允许对内部的 webpack 配置进行更细粒度的修改。

这个属性暂时不了解,后续会做详细跟进。

chainWebpack: config => {
    //配置别名
    config.resolve.alias
      .set("@",resolve("src"))
      .set("@img",resolve("src/assets/img"))
      .set("@scss",resolve("src/assets/css/common"))
    //生产环境配置
    if(isProduction){
        //删除预加载
        config.plugins.delete('preload');
        config.plugins.delete('prefetch');
        //压缩代码 
        config.optimization.minimize(true);
        //分割代码
        config.optimization.splitChunks({
            chunks: 'all'
        })
    }
  }

#CSS 

css: {
    // 是否将组件中的 CSS 提取至一个独立的 CSS 文件中 (而不是动态注入到 JavaScript 中的 inline 代码)。生产环境下是 true,开发环境下是 false
    extract: true,

    // 是否为 CSS 开启 source map。设置为 true 之后可能会影响构建的性能。默认为 false
    sourceMap: false,
    
    // 向 CSS 相关的 loader 传递选项,相比于使用 chainWebpack 手动指定 loader 更推荐上面这样做
    loaderOptions: {
      css: {
        // 这里的选项会传递给 css-loader
      },
      postcss: {
        // 这里的选项会传递给 postcss-loader
      }
    },

    // 启用 CSS modules for all css / pre-processor files.
    // 从 v4 起已弃用,请使用css.requireModuleExtension。 在 v3 中,这个选项含义与 css.requireModuleExtension 相反
    modules: false
    requireModuleExtension: false

  },

 #devServer

如果你有单独的后端开发服务器 API,并且希望在同域名下发送 API 请求 ,那么代理某些 URL 会很有用

devServer: {
  // 指定使用一个 host。默认是 localhost。如果你希望服务器外部可访问,指定如下:
  host: "0.0.0.0",
  
  // 指定要监听请求的端口号
  port: 8080

  // 当出现编译器错误或警告时,浏览器中全屏显式错误信息,且覆盖页面。默认禁用。
  overlay: {
    warnings: true,  // 如果你想要只显示编译器错误,可以只写这个
    error: true      // 如果想要显示警告和错误,两个属性都写上
  },

  // 设置为 true 时,此选项绕过主机检查。不建议这样做,因为不检查主机的应用程序容易受到 DNS 重新连接攻击。
  disableHostCheck: true,

  // 配置多个代理
  proxy: {
    "^/api": {
      target: "http://xxx.com", // 要访问的接口域名
      changeOrigin: true, //开启代理:在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
      pathRewrite: {
        "^/api": ""
      }
    },
    "/message": {
      target: "http://xxx", //目标地址
      changeOrigin: false, //是否跨域
      pathRewrite: {
        "^/message": "" //url重写
      }
    }
  }
},

针对于 配置代理 ,详细解释

1、在 localhost:3000 上有后端服务的话,你可以这样启用代理:请求到 /api/users 现在会被代理到请求 http://localhost:3000/api/users

module.exports = {
  devServer: {
    proxy: {
      '/api': 'http://localhost:3000'
    }
  }
};

2、 如果你不想始终传递 /api ,则需要重写路径:请求到 /api/users 现在会被代理到请求 http://localhost:3000/users

module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000', // 代理路径地址
        pathRewrite: {'^/api' : ''}      // 重写路径,避免每次代理都带上 /api/
      }
    }
  }
};

3、 代理跨域

module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        pathRewrite: {'^/api' : ''},    // 重写路径,避免每次代理都带上 /api/
        changeOrigin: true,  //开启代理:在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
      }
    }
  }
};

 

你可能感兴趣的:(vue专栏,webpack)