vue.config.js 配置

vue-cli3 脚手架搭建完成后,项目目录中没有 vue.config.js 文件,需要手动创建

vue.config.js 是一个可选的配置文件,如果项目的 (和 package.json 同级的) 根目录中存在这个文件,那么它会被 @vue/cli-service 自动加载。你也可以使用 package.json 中的 vue 字段,但是注意这种写法需要你严格遵照 JSON 的格式来写。


const path = require('path');
const webpack = require('webpack');
let pkg = require('./package.json');

let env = ''
if (process.env.VUE_APP_MODE === 'development') {
  env = 'dev' // 开发环境
} else if (process.env.VUE_APP_MODE === 'test') {
  env = 'test' // 测试环境
} else {
  env = 'prod' // 生产环境
}

const isProd = env === 'prod';

function resolve(dir) {
  return path.join(__dirname, dir);
}

const vueConfig = {
  entry: {
    app: './src/main.js',
  },
};

vueConfig.base = {
  //路由前缀
  publicPath: '/' + pkg.name + '/views/',
  //打包输出路径
  outputDir: 'dist/' + pkg.name + '/views',
  //主页输出路径,相对于outputDir
  indexPath: 'index.html',
  //使用vue的运行编译版本 // 使用带有浏览器内编译器的完整构建版本 这会让你的应用额外增加 10kb 左右
  runtimeCompiler: false,
  //文件名加哈希值
  filenameHashing: true,
  //开启eslint代码规范检测
  lintOnSave: true,
  //打包生成生产环境sourceMap文件 设置为 false 以加速生产环境构建
  productionSourceMap: env === 'prod' ? false : true, 
  //需要bable编译的npm模块 // babel-loader 默认会跳过 node_modules 依赖。 // 通过这个选项可以显式转译一个依赖。
  transpileDependencies: [],
  // 放置静态资源的地方 (js、css、img、fonts)  从生成的资源覆写 filename 或 chunkFilename 时,assetsDir 会被忽略。
  // assetsDir: '',
};

//设置别名
vueConfig.alias = {
  config: 'src/config/index.js',
  store: 'src/store/index.js',
  router: 'src/router/index.js',
};

//webpack环境变量
const webpackEnv = {
  MODULE_NAME: JSON.stringify(pkg.name),
  APP_VERSION: JSON.stringify(pkg.version),
  SERVER_URL: JSON.stringify(''),
};

// 开发环境
vueConfig.dev = {
  css: {
    //提取组件css为单独文件
    //MiniCssExtractPlugin暂不支持热更新, 开发模式不提取
    extract: false,
    //  是否开启 CSS source map?
    sourceMap: true,
  },
};

//生产环境
vueConfig.prod = {
  css: {
    //提取组件css为单独文件
    extract: {
      filename: 'css/[name].[contenthash:10].css',
      chunkFilename: 'css/[name].[contenthash:10].css',
    },
    sourceMap: false,
  },
  isGzip: true,
  //生产打包删除console.log
  delConsoleLog: true,
};

const buildFile = (config) => {
  // 打包后自动生成 压缩部署文件
  const FileManagerPlugin = require('filemanager-webpack-plugin');
  const nowTime = require('moment')().format('YYYYMMDDHHmm');
  const outPutPath = resolve('dist') + '/' + pkg.name;
  const zipOutPutPath = `${outPutPath}_${env}_${nowTime}`;
  // 将文件夹打包成压缩文件
  config.plugins.push(
    new FileManagerPlugin({
      onEnd: [{
          move: [
            //将当前打包环境的配置覆盖configuration.js
            {
              source: `${outPutPath}/views/configuration_${env}.js`,
              destination: `${outPutPath}/views/configuration.js`,
            },
          ],
        },
        {
          // 删除其他环境的配置文件
          delete: [`${outPutPath}/views/configuration_*.js`],
        },
        {
          copy: [{
            source: `${outPutPath}`,
            destination: `${zipOutPutPath}/${pkg.name}`,
          }, ],
          archive: [{
            source: zipOutPutPath,
            destination: `${zipOutPutPath}.zip`,
          }, ],
          delete: [zipOutPutPath],
        },
      ],
    }),
  );
};

const configEnv = isProd ? vueConfig.prod : vueConfig.dev;

module.exports = Object.assign({
    devServer: {
      //浏览器控制台输出
      clientLogLevel: 'warning',
      //开启gzip压缩
      compress: false,
      hot: true,
      // host: '0.0.0.0',
      // 配置是否是https
      //  https: false,
      port: 8086,
      useLocalIp: true,
      //自动打开浏览器
      open: true,
      // 启动热更新
      hotOnly: true,
      overlay: {
        warnings: false,
        errors: true,
      },
      watchOptions: {
        poll: false,
      },
      //跨域请求代理
      proxy: {
        '/json': {
          target: 'http://192.168.90.177:8080/',
          changeOrigin: true,
        },
        '/zzt/fcgi/common.fcgi': {
          target: 'https://webtest.ciccwm.com/',
          changeOrigin: true,
        },
      },
    },
    css: Object.assign({
      // 向 CSS 相关的 loader 传递选项 支持的 loader 有:css-loader postcss-loader sass-loader less-loader stylus-loader
        loaderOptions: {
          less: {
            lessOptions: {
              modifyVars: {
                hack: `true; @import "${resolve('src/assets/css/vantself.less')}";`,
              },
              javascriptEnabled: true,
            },
          },
        },
      },
      configEnv.css,
    ),
    configureWebpack: (config) => {
      //入口文件
      config.entry = vueConfig.entry;
      config.plugins.push(new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/));
      //webpack环境变量
      config.plugins.push(new webpack.DefinePlugin(webpackEnv));

      //把webpack runtime 插入index.html中,减少请求
      const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');
      config.plugins.push(
        new ScriptExtHtmlWebpackPlugin({
          inline: /(runtime|styles)\..*\.js$/,
        }),
      );

      // 开启代码压缩
      //js压缩-minimizer选项
      //webpack4后已改为使用terser-webpack-plugin插件
      //vuecli3默认的压缩配置在依赖中:@vue/cli-service/lib/config/terserOptions
      Object.assign(config.optimization.minimizer[0].options.terserOptions.compress, {
        warnings: false,
        drop_debugger: true,
        drop_console: configEnv.delConsoleLog,
        // pure_funcs: ['console.log']
        // exclude: /\/plugins/,
      });
      // 分割代码 相同代码放一块

      Object.assign(config.optimization, {
        //把webpack runtime单独提取出来
        runtimeChunk: 'single',
        splitChunks: {
          automaticNameDelimiter: '-', // 自定义连接符 例如index-detail.js
          //  .async对动态加载的模块进行拆分
          //  .initial只拆分入口文件的模块 (会禁止非入口文件的模块拆分)
          //  .all对所有类型的模块进行拆分。 (一般我们都会配置这个选项)
          chunks: 'all',
          //拆分文件大小下限(未压缩前的js文件大小)
          // 拆分文件大小下限(未压缩前的js文件大小)
          minSize: 60000, // 提取出来的chunk需要满足的最小size,单位是bytes
          maxSize: 600000, // maxSize比maxInitialRequest/maxAsyncRequests有更高的优先级。优先级顺序为maxInitialRequest/maxAsyncRequests < maxSize < minSize。
          cacheGroups: {
            default: false,
            vendor: {
              test: /[\\/]node_modules[\\/].+(?<!css)$/,
              name: 'vendor',
              priority: 40,
              chunks: 'initial',
              reuseExistingChunk: true,
            },
            common: {
              name: 'common',
              minChunks: 2,
              priority: -10,
              chunks: 'initial',
              reuseExistingChunk: true,
            },
            styles: {
              test: (module) =>
                module.nameForCondition &&
                /\.(s?css|vue|less)$/.test(module.nameForCondition()) &&
                !/^javascript/.test(module.type),
              name: 'styles',
              chunks: 'all',
              priority: 1,
              enforce: true,
              reuseExistingChunk: true,
            },
          },
        },
      });

      //gzip压缩
      if (configEnv.isGzip) {
        const CompressionWebpackPlugin = require('compression-webpack-plugin');
        config.plugins.push(
          new CompressionWebpackPlugin({
            filename: '[path].gz[query]',
            algorithm: 'gzip',
            test: new RegExp('\\.(' + ['js', 'css', 'html'].join('|') + ')$'),
            threshold: 2048,
            minRatio: 0.8,
            cache: true,
            deleteOriginalAssets: false,
          }),
        );
      }

      if (process.env.NODE_ENV === 'production') buildFile(config);

      // npm run build --report 构建加上参数 --report生成包文件分析页面
      if (process.env.npm_config_report) {
        const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
        config.plugins.push(new BundleAnalyzerPlugin());
      }
    },
    chainWebpack: (config) => {
      //移除 prefetch 插件
      //如果有需要 prefetch, 可以在路由引入时,用内联注释方式注明
      //import(/* webpackPrefetch: true */ './someAsyncComponent.vue')
      config.plugins.delete('prefetch');
      config.plugin('html').tap((options) => {
        options.excludeChunks = ['runtime', 'styles'];
        return options;
      });
      //webpack runtime插入index.html后,删除预加载runtime文件
      config.plugin('preload').tap((options) => {
        Object.assign(options[0], {
          fileBlacklist: [/\.map$/, /hot-update\.js$/, /runtime\S*\.js$/, /styles\S*\.js$/],
        });
        return options;
      });
      //设置别名
      for (let key in vueConfig.alias) {
        config.resolve.alias.set(key, resolve(vueConfig.alias[key]));
      }
    },
  },
  vueConfig.base,
);

posted @ 2022-02-26 19:40  sk-xm  阅读(723)  评论(0编辑  收藏  举报