适配staging环境

This commit is contained in:
wkj 2024-04-25 16:58:47 +08:00
parent 6d336d19c6
commit 7e72576914
14 changed files with 234 additions and 275 deletions

View File

@ -9,12 +9,8 @@ const ProgressBarPlugin = require('progress-bar-webpack-plugin');
const UiExtractPlugin = require('ui-extract-webpack-plugin'); const UiExtractPlugin = require('ui-extract-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin'); const CopyWebpackPlugin = require('copy-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin'); const TerserPlugin = require('terser-webpack-plugin');
const ForkTsCheckerWebpackPlugin = const ForkTsCheckerWebpackPlugin = require('./../../plugins/ForkTsCheckerWarningWebpackPlugin');
process.env.TSC_COMPILE_ON_ERROR === 'true' const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
? require('./../../plugins/ForkTsCheckerWarningWebpackPlugin')
: require('react-dev-utils/ForkTsCheckerWebpackPlugin');
const BundleAnalyzerPlugin =
require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const OakWeChatMpPlugin = require('../../plugins/WechatMpPlugin'); const OakWeChatMpPlugin = require('../../plugins/WechatMpPlugin');
@ -46,8 +42,10 @@ const copyPatterns = [].concat(pkg.copyWebpack || []).map((pattern) =>
const oakRegex = /(\/*[a-zA-Z0-9_-])*\/(lib|src|es)\/|(\\*[a-zA-Z0-9_-])*\\(lib|src|es)\\/; const oakRegex = /(\/*[a-zA-Z0-9_-])*\/(lib|src|es)\/|(\\*[a-zA-Z0-9_-])*\\(lib|src|es)\\/;
module.exports = function (webpackEnv) { module.exports = function (webpackEnv) {
// staging 把mode改为none其他跟production一样
const isEnvStaging = webpackEnv === 'staging';
const isEnvDevelopment = webpackEnv === 'development'; const isEnvDevelopment = webpackEnv === 'development';
const isEnvProduction = webpackEnv === 'production'; const isEnvProduction = webpackEnv === 'production' || isEnvStaging;
const oakFileLoader = (ext = '[ext]') => { const oakFileLoader = (ext = '[ext]') => {
return { return {
@ -91,7 +89,9 @@ module.exports = function (webpackEnv) {
target: ['web'], target: ['web'],
// Webpack noise constrained to errors and warnings // Webpack noise constrained to errors and warnings
stats: 'errors-warnings', stats: 'errors-warnings',
mode: isEnvProduction mode: isEnvStaging
? 'none'
: isEnvProduction
? 'production' ? 'production'
: isEnvDevelopment && 'development', : isEnvDevelopment && 'development',
// Stop compilation early in production // Stop compilation early in production
@ -325,9 +325,7 @@ module.exports = function (webpackEnv) {
name: 'oak-debugPanel', name: 'oak-debugPanel',
show: !isEnvProduction, show: !isEnvProduction,
}, },
split: isEnvProduction split: isEnvProduction ? true : false,
? true
: isEnvDevelopment && process.env.SPLIT === 'true',
}), }),
new webpack.DefinePlugin(env.stringified), new webpack.DefinePlugin(env.stringified),
new StylelintPlugin({ new StylelintPlugin({
@ -352,19 +350,6 @@ module.exports = function (webpackEnv) {
typescriptPath: resolve.sync('typescript', { typescriptPath: resolve.sync('typescript', {
basedir: paths.appNodeModules, basedir: paths.appNodeModules,
}), }),
// configOverwrite: {
// compilerOptions: {
// sourceMap: isEnvProduction
// ? shouldUseSourceMap
// : isEnvDevelopment,
// skipLibCheck: true,
// inlineSourceMap: false,
// declarationMap: false,
// noEmit: true,
// incremental: true,
// tsBuildInfoFile: paths.appTsBuildInfoFile,
// },
// },
configFile: paths.appTsConfig, configFile: paths.appTsConfig,
context: paths.appRootPath, context: paths.appRootPath,
diagnosticOptions: { diagnosticOptions: {

View File

@ -20,13 +20,9 @@ const paths = require('./paths');
const modules = require('./modules'); const modules = require('./modules');
const getClientEnvironment = require('./env'); const getClientEnvironment = require('./env');
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin'); const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
const ForkTsCheckerWebpackPlugin = const ForkTsCheckerWebpackPlugin = require('./../../plugins/ForkTsCheckerWarningWebpackPlugin');
process.env.TSC_COMPILE_ON_ERROR === 'true'
? require('./../../plugins/ForkTsCheckerWarningWebpackPlugin')
: require('react-dev-utils/ForkTsCheckerWebpackPlugin');
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'); const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
const BundleAnalyzerPlugin = const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const CompressionWebpackPlugin = require('compression-webpack-plugin'); const CompressionWebpackPlugin = require('compression-webpack-plugin');
const createEnvironmentHash = require('./webpack/persistentCache/createEnvironmentHash'); const createEnvironmentHash = require('./webpack/persistentCache/createEnvironmentHash');
@ -102,6 +98,8 @@ const hasJsxRuntime = (() => {
// This is the production and development configuration. // This is the production and development configuration.
// It is focused on developer experience, fast rebuilds, and a minimal bundle. // It is focused on developer experience, fast rebuilds, and a minimal bundle.
module.exports = function (webpackEnv) { module.exports = function (webpackEnv) {
// staging 把mode改为none其他跟production一样
const isEnvStaging = webpackEnv === 'staging';
const isEnvDevelopment = webpackEnv === 'development'; const isEnvDevelopment = webpackEnv === 'development';
const isEnvProduction = webpackEnv === 'production'; const isEnvProduction = webpackEnv === 'production';
@ -118,7 +116,6 @@ module.exports = function (webpackEnv) {
const shouldUseReactRefresh = env.raw.FAST_REFRESH; const shouldUseReactRefresh = env.raw.FAST_REFRESH;
// common function to get style loaders // common function to get style loaders
const getStyleLoaders = (cssOptions, preProcessor, preProcessOptions) => { const getStyleLoaders = (cssOptions, preProcessor, preProcessOptions) => {
const loaders = [ const loaders = [
@ -196,9 +193,12 @@ module.exports = function (webpackEnv) {
}, },
{ {
loader: require.resolve(preProcessor), loader: require.resolve(preProcessor),
options: Object.assign({ options: Object.assign(
{
sourceMap: true, sourceMap: true,
}, preProcessOptions), },
preProcessOptions
),
} }
); );
} }
@ -206,14 +206,17 @@ module.exports = function (webpackEnv) {
}; };
// 读取编译配置 // 读取编译配置
const compilerConfigurationFile = path.join(paths.appRootPath, 'configuration', 'compiler.js'); const compilerConfigurationFile = path.join(
const projectConfiguration = fs.existsSync(compilerConfigurationFile) && require(compilerConfigurationFile).webpack; paths.appRootPath,
'configuration',
'compiler.js'
);
const projectConfiguration =
fs.existsSync(compilerConfigurationFile) &&
require(compilerConfigurationFile).webpack;
const getOakInclude = () => { const getOakInclude = () => {
const result = [ const result = [/oak-frontend-base/, /oak-general-business/];
/oak-frontend-base/,
/oak-general-business/,
];
if (projectConfiguration && projectConfiguration.extraOakModules) { if (projectConfiguration && projectConfiguration.extraOakModules) {
result.push(...projectConfiguration.extraOakModules); result.push(...projectConfiguration.extraOakModules);
} }
@ -381,14 +384,14 @@ module.exports = function (webpackEnv) {
stream: require.resolve('stream-browserify'), stream: require.resolve('stream-browserify'),
zlib: require.resolve('browserify-zlib'), zlib: require.resolve('browserify-zlib'),
querystring: require.resolve('querystring-es3'), querystring: require.resolve('querystring-es3'),
events: path.resolve(__dirname, '../../node_modules/events'), events: require.resolve('events/'),
os: false, os: false,
url: false, url: false,
path: false, path: false,
fs: false, fs: false,
net: false, net: false,
tls: false, tls: false,
} };
if ( if (
projectConfiguration && projectConfiguration &&
projectConfiguration.resolve && projectConfiguration.resolve &&
@ -917,19 +920,6 @@ module.exports = function (webpackEnv) {
typescriptPath: resolve.sync('typescript', { typescriptPath: resolve.sync('typescript', {
basedir: paths.appNodeModules, basedir: paths.appNodeModules,
}), }),
// configOverwrite: {
// compilerOptions: {
// sourceMap: isEnvProduction
// ? shouldUseSourceMap
// : isEnvDevelopment,
// skipLibCheck: true,
// inlineSourceMap: false,
// declarationMap: false,
// noEmit: true,
// incremental: true,
// tsBuildInfoFile: paths.appTsBuildInfoFile,
// },
// },
configFile: paths.appTsConfig, configFile: paths.appTsConfig,
context: paths.appRootPath, context: paths.appRootPath,
diagnosticOptions: { diagnosticOptions: {
@ -1039,7 +1029,6 @@ module.exports = function (webpackEnv) {
react: 'React', react: 'React',
'react-dom': 'ReactDOM', 'react-dom': 'ReactDOM',
'@wangeditor/editor': 'wangEditor', '@wangeditor/editor': 'wangEditor',
// '@wangeditor/basic-modules': 'WangEditorBasicModules', 这里跑起来初始化会有个BUG先不弄了
'@fingerprintjs/fingerprintjs': 'FingerprintJS', '@fingerprintjs/fingerprintjs': 'FingerprintJS',
'bn.js': 'BN', 'bn.js': 'BN',
}, },

View File

@ -31,14 +31,7 @@ async function build(cmd) {
(0, makeRouter_1.default)({ subdir }, mode === 'development'); (0, makeRouter_1.default)({ subdir }, mode === 'development');
// makeDependency 放到npm install之后做一次 // makeDependency 放到npm install之后做一次
// makeDep(''); // makeDep('');
//ts类型检查 waring 还是error, (0, tip_style_1.Success)(`${(0, tip_style_1.success)(`build ${target} environment:${mode} ${['development'].includes(mode) ? `devMode:${devMode}` : ''}`)}`);
//主要web受影响error级别的话 控制台和网页都报错warning级别的话 控制台报错
// development/staging/production
const errorLevel = cmd.check !== 'error';
(0, tip_style_1.Success)(`${(0, tip_style_1.success)(`build ${target} environment:${mode} ${['development'].includes(mode) ? `devMode:${devMode}` : ''} ${['mp', 'wechatMp'].includes(target) &&
['development'].includes(mode)
? `split:${!!cmd.split}`
: ''}`)}`);
if (['mp', 'wechatMp'].includes(target)) { if (['mp', 'wechatMp'].includes(target)) {
const mpFileMap = { const mpFileMap = {
production: 'build-mp.js', production: 'build-mp.js',
@ -50,11 +43,9 @@ async function build(cmd) {
`NODE_TARGET=${target}`, `NODE_TARGET=${target}`,
`OAK_DEV_MODE=${devMode}`, `OAK_DEV_MODE=${devMode}`,
`SUB_DIR_NAME=${subdir}`, `SUB_DIR_NAME=${subdir}`,
`TSC_COMPILE_ON_ERROR=${errorLevel}`,
`COMPILE_ANALYZE=${!!cmd.analyze}`, `COMPILE_ANALYZE=${!!cmd.analyze}`,
`GENERATE_SOURCEMAP=${!!cmd.sourcemap}`, `GENERATE_SOURCEMAP=${!!cmd.sourcemap}`,
`PROD=${!!cmd.prod}`, `PROD=${!!cmd.prod}`,
`SPLIT=${!!cmd.split}`,
!!cmd.memoryLimit && `MEMORY_LIMIT=${cmd.memoryLimit}`, !!cmd.memoryLimit && `MEMORY_LIMIT=${cmd.memoryLimit}`,
`node`, `node`,
cmd.memoryLimit && `--max_old_space_size=${cmd.memoryLimit}`, cmd.memoryLimit && `--max_old_space_size=${cmd.memoryLimit}`,
@ -82,7 +73,6 @@ async function build(cmd) {
`NODE_TARGET=${target}`, `NODE_TARGET=${target}`,
`OAK_DEV_MODE=${devMode}`, `OAK_DEV_MODE=${devMode}`,
`SUB_DIR_NAME=${subdir}`, `SUB_DIR_NAME=${subdir}`,
`TSC_COMPILE_ON_ERROR=${errorLevel}`,
`COMPILE_ANALYZE=${!!cmd.analyze}`, `COMPILE_ANALYZE=${!!cmd.analyze}`,
`GENERATE_SOURCEMAP=${!!cmd.sourcemap}`, `GENERATE_SOURCEMAP=${!!cmd.sourcemap}`,
`PROD=${!!cmd.prod}`, `PROD=${!!cmd.prod}`,

View File

@ -231,7 +231,7 @@ async function create(dirName, cmd) {
} }
// 获取package.json内容 // 获取package.json内容
const packageJson = (0, template_1.packageJsonContent)({ const packageJson = (0, template_1.packageJsonContent)({
name: DEFAULT_PROJECT_NAME, name: DEFAULT_PROJECT_NAME, // 后面再统一rename
version, version,
description, description,
cliName: config_1.CLI_NAME, cliName: config_1.CLI_NAME,

View File

@ -62,12 +62,10 @@ commander_1.default
.option('--sourceMap', 'sourceMap') .option('--sourceMap', 'sourceMap')
.option('--analyze', 'analyze') .option('--analyze', 'analyze')
.option('--prod', 'prod') .option('--prod', 'prod')
.option('--split', 'split')
.option('--memoryLimit <memoryLimit>', 'memoryLimit of node') .option('--memoryLimit <memoryLimit>', 'memoryLimit of node')
.option('-t, --target <target>', 'target') .option('-t, --target <target>', 'target')
.option('-m, --mode <mode>', 'mode') .option('-m, --mode <mode>', 'mode')
.option('-d, --subDir <subDirName>', 'subDirName') .option('-d, --subDir <subDirName>', 'subDirName')
.option('-c, --check <level>', 'level')
.option('-p, --port <port>', 'port') .option('-p, --port <port>', 'port')
.option('-dm, --devMode <devMode>', 'devMode') .option('-dm, --devMode <devMode>', 'devMode')
.description('build project of start on demand') .description('build project of start on demand')
@ -80,7 +78,6 @@ commander_1.default
.option('-t, --target <target>', 'target') .option('-t, --target <target>', 'target')
.option('-m, --mode <mode>', 'mode') .option('-m, --mode <mode>', 'mode')
.option('-d, --subDir <subDirName>', 'subDirName') .option('-d, --subDir <subDirName>', 'subDirName')
.option('-c, --check <level>', 'level')
.option('-p, --platform <platform>', 'platform') .option('-p, --platform <platform>', 'platform')
.description('build project of build on demand') .description('build project of build on demand')
.action(build_1.default); .action(build_1.default);

View File

@ -16,6 +16,7 @@ const sticky_1 = require("@socket.io/sticky");
const socket_io_1 = require("socket.io"); const socket_io_1 = require("socket.io");
const DATA_SUBSCRIBER_NAMESPACE = '/ds'; const DATA_SUBSCRIBER_NAMESPACE = '/ds';
const SERVER_SUBSCRIBER_NAMESPACE = process.env.OAK_SSUB_NAMESPACE || '/ssub'; const SERVER_SUBSCRIBER_NAMESPACE = process.env.OAK_SSUB_NAMESPACE || '/ssub';
const ExceptionMask = '内部不可知错误';
function concat(...paths) { function concat(...paths) {
return paths.reduce((prev, current) => { return paths.reduce((prev, current) => {
if (current.startsWith('/')) { if (current.startsWith('/')) {
@ -72,7 +73,7 @@ async function startup(path, connector, omitWatchers, omitTimers, routine) {
catch (err) { catch (err) {
console.error(err); console.error(err);
const { request } = ctx; const { request } = ctx;
const exception = err instanceof types_1.OakException ? err : new types_1.OakException('内部不可知错误'); const exception = err instanceof types_1.OakException ? err : new types_1.OakException(serverConfiguration?.internalExceptionMask || ExceptionMask);
const { body } = connector.serializeException(exception, request.headers, request.body); const { body } = connector.serializeException(exception, request.headers, request.body);
ctx.response.body = body; ctx.response.body = body;
return; return;

View File

@ -260,6 +260,11 @@ function packageJsonContent({ name, version, description, cliName, cliBinName, i
"last 1 chrome version", "last 1 chrome version",
"last 1 firefox version", "last 1 firefox version",
"last 1 safari version" "last 1 safari version"
],
"staging": [
">0.2%",
"not dead",
"not op_mini all"
] ]
}, },
"copyWebpack": [] "copyWebpack": []

View File

@ -7,7 +7,7 @@ const webpack = require('webpack');
const chalk = require('chalk'); const chalk = require('chalk');
const fs = require('fs-extra'); const fs = require('fs-extra');
const configFactory = require('../config/mp/webpack.config'); const configFactory = require('../config/mp/webpack.config');
const config = configFactory('production'); const config = configFactory('staging');
const paths = require('../config/mp/paths'); const paths = require('../config/mp/paths');
const getClientEnvironment = require('../config/mp/env'); const getClientEnvironment = require('../config/mp/env');

View File

@ -47,7 +47,7 @@ const argv = process.argv.slice(2);
const writeStatsJson = argv.indexOf('--stats') !== -1; const writeStatsJson = argv.indexOf('--stats') !== -1;
// Generate configuration // Generate configuration
const config = configFactory('production'); const config = configFactory('staging');
// We require that you explicitly set browsers and do not fall back to // We require that you explicitly set browsers and do not fall back to
// browserslist defaults. // browserslist defaults.

View File

@ -46,19 +46,11 @@ export default async function build(cmd: any) {
makeRouter({ subdir }, mode === 'development'); makeRouter({ subdir }, mode === 'development');
// makeDependency 放到npm install之后做一次 // makeDependency 放到npm install之后做一次
// makeDep(''); // makeDep('');
//ts类型检查 waring 还是error,
//主要web受影响error级别的话 控制台和网页都报错warning级别的话 控制台报错
// development/staging/production
const errorLevel = cmd.check !== 'error';
Success( Success(
`${success( `${success(
`build ${target} environment:${mode} ${ `build ${target} environment:${mode} ${
['development'].includes(mode) ? `devMode:${devMode}` : '' ['development'].includes(mode) ? `devMode:${devMode}` : ''
} ${
['mp', 'wechatMp'].includes(target) &&
['development'].includes(mode)
? `split:${!!cmd.split}`
: ''
}` }`
)}` )}`
); );
@ -75,11 +67,9 @@ export default async function build(cmd: any) {
`NODE_TARGET=${target}`, `NODE_TARGET=${target}`,
`OAK_DEV_MODE=${devMode}`, `OAK_DEV_MODE=${devMode}`,
`SUB_DIR_NAME=${subdir}`, `SUB_DIR_NAME=${subdir}`,
`TSC_COMPILE_ON_ERROR=${errorLevel}`,
`COMPILE_ANALYZE=${!!cmd.analyze}`, `COMPILE_ANALYZE=${!!cmd.analyze}`,
`GENERATE_SOURCEMAP=${!!cmd.sourcemap}`, `GENERATE_SOURCEMAP=${!!cmd.sourcemap}`,
`PROD=${!!cmd.prod}`, `PROD=${!!cmd.prod}`,
`SPLIT=${!!cmd.split}`,
!!cmd.memoryLimit && `MEMORY_LIMIT=${cmd.memoryLimit}`, !!cmd.memoryLimit && `MEMORY_LIMIT=${cmd.memoryLimit}`,
`node`, `node`,
cmd.memoryLimit && `--max_old_space_size=${cmd.memoryLimit}`, cmd.memoryLimit && `--max_old_space_size=${cmd.memoryLimit}`,
@ -109,7 +99,6 @@ export default async function build(cmd: any) {
`NODE_TARGET=${target}`, `NODE_TARGET=${target}`,
`OAK_DEV_MODE=${devMode}`, `OAK_DEV_MODE=${devMode}`,
`SUB_DIR_NAME=${subdir}`, `SUB_DIR_NAME=${subdir}`,
`TSC_COMPILE_ON_ERROR=${errorLevel}`,
`COMPILE_ANALYZE=${!!cmd.analyze}`, `COMPILE_ANALYZE=${!!cmd.analyze}`,
`GENERATE_SOURCEMAP=${!!cmd.sourcemap}`, `GENERATE_SOURCEMAP=${!!cmd.sourcemap}`,
`PROD=${!!cmd.prod}`, `PROD=${!!cmd.prod}`,

View File

@ -71,12 +71,10 @@ program
.option('--sourceMap', 'sourceMap') .option('--sourceMap', 'sourceMap')
.option('--analyze', 'analyze') .option('--analyze', 'analyze')
.option('--prod', 'prod') .option('--prod', 'prod')
.option('--split', 'split')
.option('--memoryLimit <memoryLimit>', 'memoryLimit of node') .option('--memoryLimit <memoryLimit>', 'memoryLimit of node')
.option('-t, --target <target>', 'target') .option('-t, --target <target>', 'target')
.option('-m, --mode <mode>', 'mode') .option('-m, --mode <mode>', 'mode')
.option('-d, --subDir <subDirName>', 'subDirName') .option('-d, --subDir <subDirName>', 'subDirName')
.option('-c, --check <level>', 'level')
.option('-p, --port <port>', 'port') .option('-p, --port <port>', 'port')
.option('-dm, --devMode <devMode>', 'devMode') .option('-dm, --devMode <devMode>', 'devMode')
.description('build project of start on demand') .description('build project of start on demand')
@ -89,7 +87,6 @@ program
.option('-t, --target <target>', 'target') .option('-t, --target <target>', 'target')
.option('-m, --mode <mode>', 'mode') .option('-m, --mode <mode>', 'mode')
.option('-d, --subDir <subDirName>', 'subDirName') .option('-d, --subDir <subDirName>', 'subDirName')
.option('-c, --check <level>', 'level')
.option('-p, --platform <platform>', 'platform') .option('-p, --platform <platform>', 'platform')
.description('build project of build on demand') .description('build project of build on demand')
.action(build); .action(build);

View File

@ -13,10 +13,11 @@ import { SyncContext } from 'oak-domain/lib/store/SyncRowStore';
import { createAdapter } from "@socket.io/cluster-adapter"; import { createAdapter } from "@socket.io/cluster-adapter";
import { setupWorker } from "@socket.io/sticky"; import { setupWorker } from "@socket.io/sticky";
import { Server, ServerOptions } from "socket.io"; import { Server, ServerOptions } from "socket.io";
import { AccessConfiguration, ServerConfiguration } from 'oak-domain/lib/types/Configuration'; import { ServerConfiguration } from 'oak-domain/lib/types/Configuration';
const DATA_SUBSCRIBER_NAMESPACE = '/ds'; const DATA_SUBSCRIBER_NAMESPACE = '/ds';
const SERVER_SUBSCRIBER_NAMESPACE = process.env.OAK_SSUB_NAMESPACE || '/ssub'; const SERVER_SUBSCRIBER_NAMESPACE = process.env.OAK_SSUB_NAMESPACE || '/ssub';
const ExceptionMask = '内部不可知错误';
function concat(...paths: string[]) { function concat(...paths: string[]) {
return paths.reduce( return paths.reduce(
@ -88,7 +89,7 @@ export async function startup<ED extends EntityDict & BaseEntityDict, FrontCxt e
catch (err) { catch (err) {
console.error(err); console.error(err);
const { request } = ctx; const { request } = ctx;
const exception = err instanceof OakException ? err : new OakException('内部不可知错误'); const exception = err instanceof OakException ? err : new OakException(serverConfiguration?.internalExceptionMask || ExceptionMask);
const { body } = connector.serializeException(exception, request.headers, request.body); const { body } = connector.serializeException(exception, request.headers, request.body);
ctx.response.body = body; ctx.response.body = body;
return; return;

View File

@ -278,6 +278,11 @@ export function packageJsonContent({
"last 1 chrome version", "last 1 chrome version",
"last 1 firefox version", "last 1 firefox version",
"last 1 safari version" "last 1 safari version"
],
"staging": [
">0.2%",
"not dead",
"not op_mini all"
] ]
}, },
"copyWebpack": [] "copyWebpack": []

View File

@ -119,7 +119,7 @@
var tip = document.createElement('div'); var tip = document.createElement('div');
var closeBtn = document.createElement('img'); var closeBtn = document.createElement('img');
var contentHTML = var contentHTML =
'您当前使用的浏览器可能会出现界面显示异常或功能无法正常使用等问题,建议下载使用最新的 360 极速浏览器并切换到极速模式。'; '您当前使用的浏览器可能会出现界面显示异常或功能无法正常使用等问题,建议下载使用谷歌火狐edge等新版本浏览器。';
var handleClickClose = function (event) { var handleClickClose = function (event) {
document.body.removeChild(tip); document.body.removeChild(tip);
}; };