提交 c84edffb authored 作者: 王鹏飞's avatar 王鹏飞

refactor: 构建工具升级为vite

上级 46e9b92f
module.exports = {
domain: 'dev.ezijing.com',
url: 'https://learn-api2.ezijing.com/api',
webpack: {
externals: {
CKEDITOR: 'window.CKEDITOR',
Base64: 'window.Base64',
md5: 'window.md5',
regeneratorRuntime: 'window.regeneratorRuntime',
wx: 'window.wx',
WeixinJSBridge: 'window.WeixinJSBridge'
},
devServer: {
proxy: {
/* 多个代理 */
// '/api': {
// target: $GLOBAL.webConf.url,
// selfHandleResponse: false,
// // selfHandleResponse: true, // 自定义 响应结构
// secure: false, // 如果是https接口,需要配置这个参数
// changeOrigin: true, // 如果接口跨域,需要进行这个参数配置
// followRedirects: true, // 由于重定向307,所以跟随重定向直接返回一个接口
// logLevel: 'info', // 日志打印级别
// headers: {
// 'Referer': $GLOBAL.webConf.url
// },
// pathRewrite: {
// '^/api': '/' // 需要rewrite重写的
// }
// }
}
}
},
ProvidePlugin: {},
others: {
baseUrl: 'https://learn-api2.ezijing.com',
loginUrl: 'https://login2.ezijing.com/xlearn/login/index',
xtrainingUrl: 'https://x-training2.ezijing.com'
}
}
module.exports = {
url: '/',
DesDir: './client-dist',
isUploadStatic: false,
webpack: {
externals: {
CKEDITOR: 'window.CKEDITOR',
Base64: 'window.Base64',
md5: 'window.md5',
regeneratorRuntime: 'window.regeneratorRuntime',
wx: 'window.wx',
WeixinJSBridge: 'window.WeixinJSBridge'
}
},
ProvidePlugin: {},
others: {
baseUrl: 'https://learn-api.ezijing.com',
loginUrl: 'https://login.ezijing.com/xlearn/login/index',
xtrainingUrl: 'https://x-training.ezijing.com'
}
}
module.exports = {
url: '/',
DesDir: './client-dist',
isUploadStatic: false,
webpack: {
externals: {
CKEDITOR: 'window.CKEDITOR',
Base64: 'window.Base64',
md5: 'window.md5',
regeneratorRuntime: 'window.regeneratorRuntime',
wx: 'window.wx',
WeixinJSBridge: 'window.WeixinJSBridge'
}
},
ProvidePlugin: {},
others: {
baseUrl: 'https://learn-api2.ezijing.com',
loginUrl: 'https://login2.ezijing.com/xlearn/login/index',
xtrainingUrl: 'https://x-training2.ezijing.com'
}
}
# 查到当前目录就可以了,不用再往下查找
root = true
# 对所有文件制定规范
[*]
charset = utf-8 # 字符编码
end_of_line = lf # 从左往右写
indent_size = 2 # tab键长度2个空格
indent_style = space
insert_final_newline = true # 保存自动加上一个空行
trim_trailing_whitespace = true # 每行最后空格去掉
VITE_BASE_URL=https://learn-api.ezijing.com
VITE_LOGIN_URL=https://login.ezijing.com/xlearn/login/index
VITE_X_TRAINING_URL=https://x-training.ezijing.com
VITE_BASE_URL=https://learn-api2.ezijing.com
VITE_LOGIN_URL=https://login2.ezijing.com/xlearn/login/index
VITE_X_TRAINING_URL=https://x-training2.ezijing.com
VITE_BASE_URL=https://learn-api2.ezijing.com
VITE_LOGIN_URL=https://login2.ezijing.com/xlearn/login/index
VITE_X_TRAINING_URL=https://x-training2.ezijing.com
{
"extends": "standard",
"plugins": ["html"],
"parser": "vue-eslint-parser",
"parserOptions": {
"parser": "babel-eslint",
"sourceType": "module"
},
"rules": {
"no-new": "off",
"no-debugger": "off",
"space-before-function-paren": "off"
},
"globals": {
"CKEDITOR": false,
"Base64": false,
"md5": false,
"$": false,
"window": false,
"webConf": false,
"wx": false,
"WeixinJSBridge": false,
"Aliplayer": false
}
}
module.exports = {
env: {
node: true
},
extends: ['plugin:vue/essential', 'standard'],
rules: {
'vue/comment-directive': 'off',
'space-before-function-paren': 'off'
}
}
.DS_Store
node_modules
npm-debug.log
upload_tmp
# code protect - prevent submit code below
/dist
/client-dist
.DS_Store
dist
dist-ssr
*.local
.DS_Store
node_modules
npm-debug.log
# code protect - prevent submit code below
var semver = require('semver')
var requiredVersion = require('../package.json').engines.node
function checkNodeVersion (wanted, id) {
if (!semver.satisfies(process.version, wanted)) {
console.log('\x1b[91m%s\x1B[0m',
'You are using Node ' + process.version + ', but this version of ' + id +
' requires Node ' + wanted + '.\nPlease upgrade your Node version.'
)
process.exit(1)
}
}
checkNodeVersion(requiredVersion, '`node uploadAliyunCDN.js`')
const isDev = process.env.NODE_ENV
const RegStrs = require('./regExpStr.js')
let config = {
isDev: isDev,
ResDir: 'src',
DesDir: '../client-dist',
HtmlPath: 'src/index.html',
IcoPath: 'src/assets/favicon.ico',
JsPath: 'src/main.js',
isHttps: true,
isEnableToIphoneDebugger: false,
CDN_BASE: 'https://zws-imgs-pub.ezijing.com/',
CDN_DIR: 'static/build/learn-mba/',
isUploadStatic: false,
webpack: {}
}
config.RegStrs = RegStrs
let vueClientConfig = {}
config.domain = ''
if (config.isDev === 'development') {
config.url = 'http://' + config.domain + ':12002'
try {
vueClientConfig = require('../.config.dev.js')
} catch (error) {
vueClientConfig = {}
console.error('没有开发环境配置文件 -- `.config.dev.js`,正在使用默认配置')
}
} else if(config.isDev === 'test') {
config.url = '//api.ezijing.com'
try {
vueClientConfig = require('../.config.test.js')
} catch (error) {
vueClientConfig = {}
console.error('没有测试环境配置文件 -- `.config.test.js`,正在使用默认配置')
}
} else {
config.url = '//api.ezijing.com'
try {
vueClientConfig = require('../.config.pro.js')
} catch (error) {
vueClientConfig = {}
console.error('没有生产环境配置文件 -- `.config.pro.js`,正在使用默认配置')
}
}
for (let k in vueClientConfig) {
config[k] = vueClientConfig[k]
}
module.exports = config
const fs = require('fs')
const path = require('path')
const request = require('request')
const _conf = require('./config')
fs.writeFileSync(path.join(__dirname, _conf.domain + '.key'), '', { encoding: 'utf8', mode: 0o755 })
fs.writeFileSync(path.join(__dirname, _conf.domain + '.pem'), '', { encoding: 'utf8', mode: 0o755 })
request('https://ssl.godzyx.com/' + _conf.domain + '/' + _conf.domain + '.key?get=allow').pipe(fs.createWriteStream(path.join(__dirname, _conf.domain + '.key')))
request('https://ssl.godzyx.com/' + _conf.domain + '/' + _conf.domain + '.pem?get=allow').pipe(fs.createWriteStream(path.join(__dirname, _conf.domain + '.pem')))
/* 由于正则表达式,不能进行跟 gulpfile 中 去注释 在一起 */
module.exports = {
regExp_static: /('|"|`)[\.|\/]*?static\/(.*?\.(png|jpe?g|gif|svg|ico)(\?.*)?)\1/g
}
const _conf = require('./config')
module.exports = function (source) {
if (_conf.isDev !== 'development') {
return source
.replace(_conf.RegStrs.regExp_static, '$1' + _conf.CDN_BASE + _conf.CDN_DIR + 'static/$2$1')
} else {
return source
}
}
const fs = require('fs')
const path = require('path')
const OSS = require('ali-oss')
const conf = require('./config')
const client = new OSS({
region: 'oss-cn-beijing',
accessKeyId: 'LTAIOTuuLTaWoGJj',
accessKeySecret: 'dE5tTGm2lh35eItct2krW2DeH2lf2I',
bucket: 'zws-imgs-pub'
})
const headers = {
'x-oss-traffic-limit': 8 * 1024 * 100 * 100
}
const DIR_PATH = path.join(__dirname, '../' + conf.DesDir)
const PREFIX_PATH = conf.CDN_DIR
const isUploadStatic = conf.isUploadStatic
let fileCount = 1
async function uploadFile (prefixPath, dirFileName) {
try {
const upFilePath = prefixPath.replace(new RegExp(DIR_PATH, 'gi'), '') + path.basename(dirFileName)
const result = await client.put(prefixPath + path.basename(dirFileName), dirFileName, {
headers,
timeout: 600000
})
if (result.res.status === 200) {
console.log('第' + fileCount++ + '个文件,已上传:' + conf.CDN_BASE + upFilePath)
return { status: 200 }
}
} catch (err) {
console.log('第' + fileCount++ + '个文件,上传失败:' + conf.CDN_BASE + upFilePath)
return { status: 500, err: err }
}
}
function uploadfiles (dirPath, callback) {
const files = fs.readdirSync(dirPath)
files.forEach(function (filename, i) {
const filedir = path.join(dirPath, filename)
const info = fs.statSync(filedir)
if (info.isDirectory()) {
if (!(isUploadStatic ? true : filename !== 'static')) { return }
const morePath = filedir.replace(new RegExp(DIR_PATH, 'gi'), '') + '/'
uploadfiles(filedir, function (filedir) {
uploadFile(path.join(PREFIX_PATH, morePath), filedir)
})
} else {
if (typeof callback === 'function') {
callback(filedir)
} else {
uploadFile(PREFIX_PATH, filedir)
}
}
})
return true
}
uploadfiles(DIR_PATH, null)
const path = require('path')
const webpack = require('webpack')
const WebpackMerge = require('webpack-merge')
const _conf = require('./config')
const $GLOBAL = {
isDev: _conf.isDev,
ResDir: _conf.ResDir,
'isEnableToIphoneDebugger': _conf.isEnableToIphoneDebugger,
templatePath: path.resolve(__dirname, '../' + _conf.HtmlPath),
icoPath: _conf.IcoPath,
EntryPath: path.resolve(__dirname, '../' + _conf.JsPath),
OutputPath: path.resolve(__dirname, '../' + _conf.DesDir),
jsName: 'resources/[name].[chunkhash:8].js',
cssName: 'resources/[name].[contenthash:12].css',
resName: 'resources/[name].[hash:8].[ext]',
EntryStaticPath: path.resolve(__dirname, '../' + 'static'),
OutputStaticPath: path.resolve(__dirname, '../' + _conf.DesDir + '/static'),
RegStrs: _conf.RegStrs,
webConf: {
'isDev': _conf.isDev,
'serverPort': process.env.SERVER_PORT || 8000,
'isEnableToIphoneDebugger': _conf.isEnableToIphoneDebugger,
'domain': _conf.domain,
'url': _conf.url,
'isHttps': _conf.isHttps,
'apiBaseURL': _conf.apiBaseURL || '/api',
'CDN_PATH': _conf.CDN_BASE + _conf.CDN_DIR,
'others': _conf.others || {}
},
externals: _conf.webpack.externals || {},
ProvidePlugin: _conf.webpack.ProvidePlugin || {},
BaseConfig: {}
}
$GLOBAL.BaseConfig = {
target: 'web',
entry: $GLOBAL.EntryPath,
output: {
filename: $GLOBAL.jsName,
path: $GLOBAL.OutputPath,
publicPath: $GLOBAL.isDev === 'development' ? '/' : $GLOBAL.webConf.CDN_PATH
},
resolve: {
alias: {
'@': path.resolve(__dirname, '../' + $GLOBAL.ResDir),
'@api': path.resolve(__dirname, '../' + $GLOBAL.ResDir + '/api'),
'@action': path.resolve(__dirname, '../' + $GLOBAL.ResDir + '/action'),
'@tool': path.resolve(__dirname, '../' + $GLOBAL.ResDir + '/tool')
},
extensions: ['.js', '.json', '.jsx', '.vue']
},
module: {
rules: [
{
test: /\.(vue|js|jsx)$/,
loader: 'eslint-loader',
exclude: /node_modules/,
enforce: 'pre'
},
{
test: /\.(vue|js|jsx)|((sa|sc|c)ss)$/,
loader: './build/stringReplaceLoader.js',
exclude: /node_modules/,
enforce: 'pre'
},
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /(\.jsx|\.js)$/,
exclude: /(node_modules)|(dist)/,
loader: 'babel-loader',
options: {
presets: [[
'@babel/preset-env',
{
"targets": {
"browsers": [
"last 2 versions",
"ie >= 11"
],
},
corejs: '3.6.5',
useBuiltIns: 'usage'
}
]],
plugins: [
'@babel/plugin-syntax-jsx',
'@babel/plugin-proposal-class-properties',
'@babel/plugin-syntax-dynamic-import',
[
'@babel/plugin-transform-runtime',
{
corejs: 3,
helpers: true,
regenerator: true,
useESModules: false
}
]
]
}
},
{
test: /\.(png|jpe?g|gif|svg|ico)(\?.*)?$/,
use: {
loader: 'url-loader',
options: {
esModule: false,
limit: 4096,
name: $GLOBAL.resName
}
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: $GLOBAL.resName
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: $GLOBAL.resName
}
}
]
},
externals: {
},
plugins: [
new webpack.DefinePlugin({
'webConf': JSON.stringify($GLOBAL.webConf)
}),
new webpack.ProvidePlugin($GLOBAL.ProvidePlugin)
]
}
$GLOBAL.BaseConfig = WebpackMerge($GLOBAL.BaseConfig, _conf.webpack)
module.exports = $GLOBAL
const fs = require('fs')
const path = require('path')
const webpack = require('webpack')
const WebpackMerge = require('webpack-merge')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const AutoPrefixer = require('autoprefixer')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const HtmlReplaceWebpackPlugin = require('html-replace-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const VconsoleWebpackPlugin = require('vconsole-webpack-plugin')
const $GLOBAL = require('./webpack.base.conf')
let config = null
if ($GLOBAL.isDev === 'development') {
config = WebpackMerge($GLOBAL.BaseConfig, {
mode: 'development',
devtool: '#cheap-module-eval-source-map',
output: {
filename: '[name].js'
},
devServer: {
port: $GLOBAL.webConf.serverPort,
disableHostCheck: false,
host: $GLOBAL.webConf.domain || 'localhost',
http2: false,
https: $GLOBAL.webConf.isHttps && {
key: fs.readFileSync(path.join(__dirname, $GLOBAL.webConf.domain + '.key')),
cert: fs.readFileSync(path.join(__dirname, $GLOBAL.webConf.domain + '.pem'))
},
overlay: {
errors: true
},
historyApiFallback: {
index: '/index.html'
},
proxy: {
'/api': {
target: $GLOBAL.webConf.url,
selfHandleResponse: false,
secure: false,
changeOrigin: true,
followRedirects: true,
logLevel: 'info',
headers: {
'Referer': $GLOBAL.webConf.url
},
pathRewrite: {
'^/api': '/'
}
}
},
open: true,
hot: true
},
module: {
rules: [{
test: /\.(sa|sc|c)ss$/,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
plugins: [
AutoPrefixer({
'overrideBrowserslist': [
'cover 99.5%',
'ie 6-8',
'since 2015',
'last 10 iOS versions'
]
})
]
}
},
{
loader: 'sass-loader',
options: {
implementation: require('dart-sass')
}
}
]
}]
},
plugins: [
new VueLoaderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
template: $GLOBAL.templatePath,
inject: true,
favicon: $GLOBAL.icoPath
}),
new VconsoleWebpackPlugin({
filter: [],
enable: $GLOBAL.isEnableToIphoneDebugger
})
]
})
} else {
config = WebpackMerge($GLOBAL.BaseConfig, {
mode: 'production',
entry: {
app: $GLOBAL.EntryPath,
vendor: ['vue', 'vue-router', 'vue-i18n']
},
module: {
rules: [{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
}
},
'css-loader',
{
loader: 'postcss-loader',
options: {
plugins: [
AutoPrefixer({
'overrideBrowserslist': [
'cover 99.5%',
'ie 6-8',
'since 2015',
'last 10 iOS versions'
]
})
]
}
},
{
loader: 'sass-loader',
options: {
implementation: require('dart-sass')
}
}
]
}]
},
plugins: [
new CleanWebpackPlugin(['**/*'], { root: $GLOBAL.OutputPath }),
new MiniCssExtractPlugin({
filename: '[name].[contenthash:12].css',
chunkFilename: $GLOBAL.cssName
}),
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
template: $GLOBAL.templatePath,
inject: true,
favicon: $GLOBAL.icoPath,
minify: {
removeComments: true,
collapseWhitespace: true
}
}),
new HtmlReplaceWebpackPlugin([
{
pattern: $GLOBAL.RegStrs.regExp_static,
replacement: '$1' + $GLOBAL.webConf.CDN_PATH + 'static/$2$1'
}
]),
new CopyWebpackPlugin([
{
from: $GLOBAL.EntryStaticPath,
to: $GLOBAL.OutputStaticPath,
ignore: ['.*'],
transform: function (content) {
return content
}
}
]),
new VconsoleWebpackPlugin({
filter: [],
enable: $GLOBAL.isEnableToIphoneDebugger
})
],
optimization: {
runtimeChunk: {
name: 'manifest'
},
splitChunks: {
chunks: 'async',
minSize: 30000,
maxSize: 400000,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
name: false,
cacheGroups: {
vendor: {
name: 'vendor',
chunks: 'initial',
priority: -10,
reuseExistingChunk: false,
test: /node_modules\/(.*)\.js/
},
}
}
}
})
}
module.exports = config
const fs = require('fs')
const path = require('path')
const chalk = require('chalk')
const OSS = require('ali-oss')
const log = console.log
const client = new OSS({
region: 'oss-cn-beijing',
accessKeyId: 'LTAIOTuuLTaWoGJj',
accessKeySecret: 'dE5tTGm2lh35eItct2krW2DeH2lf2I',
bucket: 'webapp-pub'
})
async function uploadTarget(src, dist) {
try {
const result = await client.put(dist, path.join(__dirname, src))
log(chalk.green('上传成功', result.url))
} catch (e) {
log(chalk.red('上传失败', src))
log(e)
}
}
function generateUploadTarget(src, dist) {
fs.readdir(path.join(__dirname, src), function (err, files) {
if (err) {
log(err)
return
}
files.forEach(function (file) {
const _src = src + '/' + file
const _dist = dist + '/' + file
const stats = fs.statSync(path.join(__dirname, _src))
// 判断是否为文件
stats.isFile() && uploadTarget(_src, _dist)
// 判断是否为文件夹
stats.isDirectory() && generateUploadTarget(_src, _dist)
})
})
}
generateUploadTarget('./dist', '/website/prod/x-learn')
......@@ -25,4 +25,3 @@ NhYxrQKBgDVE4HSDqOvZOaXGRoM0pJ3uYRTTSIDGVNMZ9t2C/t3uwoyFBe+Om2t+
G6w2Gr+Dck1v+zizU3khbAHvE67rYoUtrDvae41bmLuVcnYh4UsXfhB6BWOSaQ+l
l8aQwTfmV74szsEDcFkg038zQ6Q4c8iiurYp29nwEM7/mayBGOcv
-----END RSA PRIVATE KEY-----
......@@ -68,4 +68,3 @@ oJPibfMaYkHMY3pTbOv2rzMKEoZwHDHqyC73RI9JgqqiXHw0rIL8A1uL3IrymXEr
mycTqbSozQwiiEfb+cxzY82YaNzaLpJyIst0T2QmdDDngmyd2LEmm4NKeXRrcFRh
XDDFfpIn93B7JA==
-----END CERTIFICATE-----
<!DOCTYPE html>
<html lang="zh-cn">
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta content="origin" name="referrer" />
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta charset="UTF-8" />
<link rel="icon" href="https://zws-imgs-pub.ezijing.com/pc/base/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>金融产品数字化营销职业技能等级证书学习平台</title>
<meta
name="viewport"
id="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, shrink-to-fit=no, viewport-fit=cover"
/>
<link rel="stylesheet" href="https://g.alicdn.com/de/prismplayer/2.9.3/skins/default/aliplayer-min.css" />
<link rel="stylesheet" href="//at.alicdn.com/t/font_2173492_ctgt96uojqw.css" />
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
<script src="https://g.alicdn.com/de/prismplayer/2.9.3/aliplayer-min.js"></script>
</body>
</html>
This source diff could not be displayed because it is too large. You can view the blob instead.
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论