vue3 下vue.config.js+cdn

306 阅读1分钟


const path = require('path')
const BundleAnalyzerPlugin =
  require('webpack-bundle-analyzer').BundleAnalyzerPlugin
// const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin')
const isProduction = process.env.NODE_ENV === 'production'
const isAnalyzeMode = !!process.env.ANALYZE_MODE
function resolve(dir) {
  return path.join(__dirname, dir)
}

// 使用CDN 加速优化
const externals = {
  wangeditor: 'wangEditor'
}

const cdnResource = {
  css: ['https://unpkg.com/@wangeditor/editor@latest/dist/css/style.css'],
  js: ['https://cdn.jsdelivr.net/npm/wangeditor@latest/dist/wangEditor.min.js']
}

// https://cli.vuejs.org/zh/guide/webpack.html#%E7%AE%80%E5%8D%95%E7%9A%84%E9%85%8D%E7%BD%AE%E6%96%B9%E5%BC%8F
module.exports = {
  devServer: {
    // 配置反向代理
    proxy: {
      // 当地址中有/api的时候会触发代理机制
      // '/api': {
      //   // 要代理的服务器地址  这里不用写 api
      //   target: 'http://localhost:4000',
      //   changeOrigin: true // 是否跨域
      // }
      '/prod-api': {
        // 要代理的服务器地址  这里不用写 api
        
    }
  },
  chainWebpack(config) {
    if (isProduction | isAnalyzeMode) {
      config.plugin('html').tap((args) => {
        args[0].cdn = cdnResource
        return args
      })
    }
    // 设置 svg-sprite-loader
    config.module.rule('svg').exclude.add(resolve('src/icons')).end()
    config.module
      .rule('icons')
      .test(/\.svg$/)
      .include.add(resolve('src/icons'))
      .end()
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]'
      })
      .end()
  },
  configureWebpack: (config) => {
    // https://webpack.js.org/configuration/cache/ 开启缓存
    config.cache = {
      type: 'filesystem',
      allowCollectingMemory: true
    }
    // 打包时npm包转CDN
    if (isProduction | isAnalyzeMode) {
      config.externals = externals
    }
    config.optimization.splitChunks = {
      maxInitialRequests: Infinity,
      minSize: 300 * 1024,
      chunks: 'all',
      cacheGroups: {
        elmVendor: {
          test: /[\\/]node_modules[\\/]/,
          name(module) {
            // get the name.
            // node_modules/packageName/sub/path
            // or node_modules/packageName
            const packageName = module.context.match(
              /[\\/]node_modules[\\/](.*?)([\\/]|$)/
            )[1]
            return `npm.${packageName.replace('@', '')}`
          }
        }
      }
    }
    if (isAnalyzeMode) {
      config.plugins.push(
        new BundleAnalyzerPlugin({
          analyzerMode: 'static'
        })
      )
    }
  }
}

配置 externals


const externals = {
  wangeditor: 'wangEditor'
}

配置 cdn

注意查看cdn 是否可以使用, 如果要上线,应该配置自己项目的cdn

const cdnResource = { css: ['https://unpkg.com/@wangeditor/editor@latest/dist/css/style.css'], js: ['https://cdn.jsdelivr.net/npm/wangeditor@latest/dist/wangEditor.min.js'] }

项目配置

  chainWebpack(config) {
    if (isProduction | isAnalyzeMode) {
      config.plugin('html').tap((args) => {
        args[0].cdn = cdnResource
        return args
      })
    }
  },
  configureWebpack: (config) => {
    // 打包时npm包转CDN
    if (isProduction | isAnalyzeMode) {
      config.externals = externals
    }
  },

页面配置

index.html

<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0" />
    <link rel="icon" href="<%= BASE_URL %>favicon.ico" />
    <title><%= htmlWebpackPlugin.options.title %></title>
    <!-- 使用CDN的CSS文件 -->
    <% for (var i in
    htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %>
    <link
      href="<%= htmlWebpackPlugin.options.cdn.css[i] %>"
      rel="preload"
      as="style"
    />
    <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet" />
    <% } %>
    <!-- 使用CDN加速的JS文件,配置在vue.config.js下 -->
    <% for (var i in
    htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
    <script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
    <% } %>
  </head>

  <body>
    <noscript>
      <strong
        >We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
        properly without JavaScript enabled. Please enable it to
        continue.</strong
      >
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

项目引入使用

<template>
  <div class="editor-container">
    <div id="editor-box"></div>
    <div class="bottom">
      <el-button type="primary" @click="onSubmitClick">{{
        $t('msg.article.commit')
      }}</el-button>
    </div>
  </div>
</template>

<script setup>
**import E from 'wangeditor'**
import { onMounted, defineProps, defineEmits, watch } from 'vue'
import i18next from 'i18next'
import { useStore } from 'vuex'
import { commitArticle, editArticle } from './commit'
console.log(E)
const props = defineProps({
  title: {
    required: true,
    type: String
  },
  detail: {
    type: Object
  }
})

const emits = defineEmits(['onSuccess'])

const store = useStore()

// Editor实例
let editor
// 处理离开页面切换语言导致 dom 无法被获取
let el
onMounted(() => {
  el = document.querySelector('#editor-box')
  initEditor()
})

const initEditor = () => {
  editor = new E(el)
  editor.config.zIndex = 1
  // 菜单栏提示
  editor.config.showMenuTooltips = true
  editor.config.menuTooltipPosition = 'down'

  // 国际化相关处理
  editor.config.lang = store.getters.language === 'zh' ? 'zh-CN' : 'en'
  editor.i18next = i18next

  editor.create()
}

// 编辑相关
watch(
  () => props.detail,
  (val) => {
    if (val && val.content) {
      editor.txt.html(val.content)
    }
  },
  {
    immediate: true
  }
)

const onSubmitClick = async () => {
  if (props.detail && props.detail._id) {
    // 编辑文章
    await editArticle({
      id: props.detail._id,
      title: props.title,
      content: editor.txt.html()
    })
  } else {
    // 创建文章
    await commitArticle({
      title: props.title,
      content: editor.txt.html()
    })
  }

  editor.txt.html('')
  emits('onSuccess')
}
</script>

<style lang="scss" scoped>
.editor-container {
  .bottom {
    margin-top: 20px;
    text-align: right;
  }
}
</style>