diff --git a/config/loaders/wxml-loader.js b/config/loaders/wxml-loader.js
index 0407721..8814a7b 100644
--- a/config/loaders/wxml-loader.js
+++ b/config/loaders/wxml-loader.js
@@ -5,6 +5,8 @@
const { DOMParser, XMLSerializer } = require('@xmldom/xmldom');
const { resolve, relative } = require('path');
const { isUrlRequest, urlToRequest } = require('loader-utils');
+const fs = require('fs');
+const path = require('path');
const BOOLEAN_ATTRS = [
'wx:else',
@@ -82,7 +84,9 @@ const CURRENT_LOCALE_KEY = '$_locale';
const LOCALE_CHANGE_HANDLER_NAME = '$_localeChange';
const COMMON_LOCALE_DATA = '$_common_translations';
const CURRENT_LOCALE_DATA = '$_translations';
-const WXS_PATH = 'i18n/locales.wxs';
+
+const DEFAULT_WXS_FILENAME = 'locales.wxs';
+const WXS_PATH = 'i18n' + '/' +DEFAULT_WXS_FILENAME;
function existsT(str) {
if (!str) return false;
@@ -94,10 +98,25 @@ function existsT(str) {
);
}
+function replaceDoubleSlash(str) {
+ return str.replace(/\\/g, '/');
+}
+
function replaceT(str) {
return str.replace(/t\(/g, 'i18n.t(');
}
+function getWxsCode() {
+ const BASE_PATH = path.dirname(
+ require.resolve(
+ `${process.cwd()}/node_modules/oak-frontend-base/src/platforms/wechatMp/i18n/wxs/wxs.js`
+ )
+ );
+ const code = fs.readFileSync(path.join(BASE_PATH, '/wxs.js'), 'utf-8');
+ const runner = `module.exports = { \nt: Interpreter.getMessageInterpreter() \n}`;
+ return [code, runner].join('\n');
+}
+
module.exports = async function (content) {
// loader的缓存功能
// this.cacheable && this.cacheable();
@@ -109,21 +128,24 @@ module.exports = async function (content) {
options: webpackLegacyOptions,
_module = {},
_compilation = {},
+ _compiler = {},
resourcePath,
} = this;
+ const { output } = _compiler.options;
+ const { path: outputPath } = output;
const { context, target } = webpackLegacyOptions || this;
const issuer = _compilation.moduleGraph.getIssuer(this._module);
const issuerContext = (issuer && issuer.context) || context;
const root = resolve(context, issuerContext);
let source = content;
- let relativePath; // locales.wxs相对路径
+ let wxsRelativePath; // locales.wxs相对路径
//判断是否存在i18n的t函数
if (existsT(source)) {
//判断加载的xml是否为本项目自身的文件
const isSelf = context.indexOf(projectContext) !== -1;
if (isSelf) {
//本项目xml
- relativePath = relative(
+ wxsRelativePath = relative(
context,
projectContext + '/' + WXS_PATH
).replace(/\\/g, '/');
@@ -132,7 +154,7 @@ module.exports = async function (content) {
const index = context.lastIndexOf(WeChatMpDir);
if (index !== -1) {
const p = context.substring(index + WeChatMpDir.length);
- relativePath = relative(
+ wxsRelativePath = relative(
projectContext + p,
projectContext + '/' + WXS_PATH
).replace(/\\/g, '/');
@@ -140,7 +162,7 @@ module.exports = async function (content) {
}
source =
- `` +
+ `` +
source;
}
// 注入全局message组件
@@ -174,10 +196,13 @@ module.exports = async function (content) {
!isDynamicSrc(value) &&
isUrlRequest(value, root)
) {
- if (relativePath === value) {
- // 如果出现直接读取项目下i18n/locales.wxs
- const path = projectContext + '/' + WXS_PATH;
- requests.push(path);
+ if (wxsRelativePath === value) {
+ // dist目录下生成一个i18n/locales.wxs文件
+ const path = resolve(outputPath, WXS_PATH);
+ if (!fs.existsSync(replaceDoubleSlash(path))) {
+ const wxsContent = `${getWxsCode()}`;
+ this.emitFile(WXS_PATH, wxsContent);
+ }
} else {
const path = resolve(root, value);
// const request = urlToRequest(value, root);
diff --git a/config/mp/paths.js b/config/mp/paths.js
index 495e766..11548b0 100644
--- a/config/mp/paths.js
+++ b/config/mp/paths.js
@@ -37,6 +37,7 @@ module.exports = {
dotenv: resolveApp('.env'),
appPath: resolveApp('.'),
appBuild: resolveApp(buildPath),
+ appIndexDevJs: resolveModule(resolveApp, 'src/app.dev'),
appIndexJs: resolveModule(resolveApp, 'src/app'),
appPackageJson: resolveRoot('package.json'),
appSrc: resolveApp('src'),
@@ -48,6 +49,7 @@ module.exports = {
appTsBuildInfoFile: resolveRoot('node_modules/.cache/tsconfig.tsbuildinfo'),
publicUrlOrPath: '/',
appOutSrc: resolveRoot('src'),
+ oakConfigJson: resolveApp('src/oak.config.json'),
};
diff --git a/config/mp/webpack.config.js b/config/mp/webpack.config.js
index 33d11a6..a326888 100644
--- a/config/mp/webpack.config.js
+++ b/config/mp/webpack.config.js
@@ -14,41 +14,10 @@ const getClientEnvironment = require('./env');
const paths = require('./paths');
const env = getClientEnvironment();
-
-const isEnvDevelopment = env.raw.NODE_ENV === 'development';
-const isEnvProduction = env.raw.NODE_ENV === 'production';
const pkg = require(paths.appPackageJson);
// process.env.OAK_PLATFORM: wechatMp | wechatPublic | web | node
-const relativeFileLoader = (ext = '[ext]') => {
- return {
- loader: 'file-loader',
- options: {
- useRelativePath: true,
- name: `[path][name].${ext}`,
- context: paths.appSrc,
- },
- };
-};
-
-const oakFileLoader = (ext = '[ext]') => {
- return {
- loader: 'file-loader',
- options: {
- useRelativePath: true,
- name: `[path][name].${ext}`,
- outputPath: (url, resourcePath, context) => {
- const outputPath = url.split(
- 'oak-general-business/wechatMp/'
- )[1];
- return outputPath;
- },
- context: paths.appSrc,
- },
- };
-};
-
const copyPatterns = [].concat(pkg.copyWebpack || []).map((pattern) =>
typeof pattern === 'string'
? {
@@ -57,203 +26,237 @@ const copyPatterns = [].concat(pkg.copyWebpack || []).map((pattern) =>
}
: pattern
);
-const oakReg = /oak-general-business\/wechatMp|oak-general-business\\wechatMp/;
+const oakRegex = /oak-general-business\/wechatMp|oak-general-business\\wechatMp/;
-module.exports = {
- context: paths.appSrc,
- devtool: isEnvDevelopment ? 'source-map' : false,
- mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development',
- target: 'web',
- entry: {
- app: paths.appIndexJs,
- },
- output: {
- path: paths.appBuild,
- filename: '[name].js',
- publicPath: paths.publicUrlOrPath,
- globalObject: 'global',
- },
- resolve: {
- alias: {
- '@': paths.appSrc,
- assert: require.resolve('assert'),
+module.exports = function (webpackEnv) {
+ const isEnvDevelopment = webpackEnv === 'development';
+ const isEnvProduction = webpackEnv === 'production';
+
+ const relativeFileLoader = (ext = '[ext]') => {
+ return {
+ loader: 'file-loader',
+ options: {
+ useRelativePath: true,
+ name: `[path][name].${ext}`,
+ context: paths.appSrc,
+ },
+ };
+ };
+
+ const oakFileLoader = (ext = '[ext]') => {
+ return {
+ loader: 'file-loader',
+ options: {
+ useRelativePath: true,
+ name: `[path][name].${ext}`,
+ outputPath: (url, resourcePath, context) => {
+ const outputPath = url.split(
+ 'oak-general-business/wechatMp/'
+ )[1];
+ return outputPath;
+ },
+ context: paths.appSrc,
+ },
+ };
+ };
+
+ return {
+ context: paths.appSrc,
+ devtool: isEnvDevelopment ? 'source-map' : false,
+ mode: isEnvProduction
+ ? 'production'
+ : isEnvDevelopment && 'development',
+ target: 'web',
+ entry: {
+ app: isEnvProduction ? paths.appIndexJs : paths.appIndexDevJs,
},
- extensions: paths.moduleFileExtensions.map((ext) => `.${ext}`),
- symlinks: true,
- fallback: {
- crypto: require.resolve('crypto-browserify'),
- buffer: require.resolve('safe-buffer'),
- stream: require.resolve('stream-browserify'),
+ output: {
+ path: paths.appBuild,
+ filename: '[name].js',
+ publicPath: paths.publicUrlOrPath,
+ globalObject: 'global',
},
- },
- resolveLoader: {
- // 第一种使用别名的方式引入自定义的loader
- alias: {
- 'wxml-loader': path.resolve(__dirname, '../loaders/wxml-loader.js'),
+ resolve: {
+ alias: {
+ '@': paths.appSrc,
+ assert: require.resolve('assert'),
+ },
+ extensions: paths.moduleFileExtensions.map((ext) => `.${ext}`),
+ symlinks: true,
+ fallback: {
+ crypto: require.resolve('crypto-browserify'),
+ buffer: require.resolve('safe-buffer'),
+ stream: require.resolve('stream-browserify'),
+ },
},
- // 第二种方式选查找自己的loaders文件中有没有这个loader再查找node_modules文件
- // modules: [path.resolve(__dirname, 'loaders'), 'node_modules'],
- },
- optimization: {
- // 标记未被使用的代码
- usedExports: true,
- // 删除 usedExports 标记的未使用的代码
- minimize: isEnvProduction,
- minimizer: [
- new TerserPlugin({
- extractComments: false,
- }),
- ],
- },
- module: {
- rules: [
- {
- test: /\.wxs$/,
- include: /src/,
- type: 'javascript/auto',
- use: [relativeFileLoader()],
+ resolveLoader: {
+ // 第一种使用别名的方式引入自定义的loader
+ alias: {
+ 'wxml-loader': path.resolve(
+ __dirname,
+ '../loaders/wxml-loader.js'
+ ),
},
- {
- test: /\.wxs$/,
- include: oakReg,
- type: 'javascript/auto',
- use: [relativeFileLoader()],
- },
- {
- test: /\.(png|jpg|gif|svg)$/,
- include: /src/,
- type: 'javascript/auto',
- use: relativeFileLoader(),
- },
- {
- test: /\.(png|jpg|gif|svg)$/,
- include: oakReg,
- type: 'javascript/auto',
- use: oakFileLoader(),
- },
- {
- test: /\.less$/,
- include: /src/,
- exclude: /node_modules/,
- use: [
- relativeFileLoader('wxss'),
- {
- loader: 'less-loader',
- },
- ],
- },
- {
- test: /\.less$/,
- include: oakReg,
- type: 'javascript/auto',
- use: [
- oakFileLoader('wxss'),
- {
- loader: 'less-loader',
- options: {
- lessOptions: () => {
- const oakConfigJson = require(`${paths.appSrc}/oak.config.json`);
- return {
- javascriptEnabled: true,
- modifyVars: oakConfigJson.theme,
- };
+ // 第二种方式选查找自己的loaders文件中有没有这个loader再查找node_modules文件
+ // modules: [path.resolve(__dirname, 'loaders'), 'node_modules'],
+ },
+ optimization: {
+ // 标记未被使用的代码
+ usedExports: true,
+ // 删除 usedExports 标记的未使用的代码
+ minimize: isEnvProduction,
+ minimizer: [
+ new TerserPlugin({
+ extractComments: false,
+ }),
+ ],
+ },
+ module: {
+ rules: [
+ {
+ test: /\.wxs$/,
+ include: /src/,
+ type: 'javascript/auto',
+ use: [relativeFileLoader()],
+ },
+ {
+ test: /\.wxs$/,
+ include: oakRegex,
+ type: 'javascript/auto',
+ use: [relativeFileLoader()],
+ },
+ {
+ test: /\.(png|jpg|gif|svg)$/,
+ include: /src/,
+ type: 'javascript/auto',
+ use: relativeFileLoader(),
+ },
+ {
+ test: /\.(png|jpg|gif|svg)$/,
+ include: oakRegex,
+ type: 'javascript/auto',
+ use: oakFileLoader(),
+ },
+ {
+ test: /\.less$/,
+ include: /src/,
+ exclude: /node_modules/,
+ use: [
+ relativeFileLoader('wxss'),
+ {
+ loader: 'less-loader',
+ },
+ ],
+ },
+ {
+ test: /\.less$/,
+ include: oakRegex,
+ type: 'javascript/auto',
+ use: [
+ oakFileLoader('wxss'),
+ {
+ loader: 'less-loader',
+ options: {
+ lessOptions: () => {
+ const oakConfigJson = require(paths.oakConfigJson);
+ return {
+ javascriptEnabled: true,
+ modifyVars: oakConfigJson.theme,
+ };
+ },
},
},
- },
- ],
- },
- {
- test: /\.js$/,
- exclude: /node_modules/,
- loader: 'babel-loader',
- },
- {
- test: /\.ts$/,
- exclude: /node_modules/,
- loader: 'ts-loader',
- },
- // {
- // test: /\.json$/,
- // include: /src/,
- // exclude: /node_modules/,
- // type: 'asset/resource',
- // generator: {
- // filename: `[path][name].[ext]`,
- // },
- // // type: 'javascript/auto',
- // // use: [relativeFileLoader('json')],
- // },
- {
- test: /\.(xml|wxml)$/,
- include: /src/,
- // type: 'asset/resource',
- // generator: {
- // filename: `[path][name].[ext]`,
+ ],
+ },
+ {
+ test: /\.js$/,
+ exclude: /node_modules/,
+ loader: 'babel-loader',
+ },
+ {
+ test: /\.ts$/,
+ exclude: /node_modules/,
+ loader: 'ts-loader',
+ },
+ // {
+ // test: /\.json$/,
+ // include: /src/,
+ // exclude: /node_modules/,
+ // type: 'asset/resource',
+ // generator: {
+ // filename: `[path][name].[ext]`,
+ // },
+ // // type: 'javascript/auto',
+ // // use: [relativeFileLoader('json')],
// },
- type: 'javascript/auto',
- use: [
- relativeFileLoader('wxml'),
- {
- loader: 'wxml-loader',
- options: {
- context: paths.appSrc,
+ {
+ test: /\.(xml|wxml)$/,
+ include: /src/,
+ type: 'javascript/auto',
+ use: [
+ relativeFileLoader('wxml'),
+ {
+ loader: 'wxml-loader',
+ options: {
+ context: paths.appSrc,
+ },
},
- },
- ],
- },
- {
- test: /\.(xml|wxml)$/,
- include: oakReg,
- type: 'javascript/auto',
- use: [
- oakFileLoader('wxml'),
- {
- loader: 'wxml-loader',
- options: {
- context: paths.appSrc,
+ ],
+ },
+ {
+ test: /\.(xml|wxml)$/,
+ include: oakRegex,
+ type: 'javascript/auto',
+ use: [
+ oakFileLoader('wxml'),
+ {
+ loader: 'wxml-loader',
+ options: {
+ context: paths.appSrc,
+ },
},
- },
- ],
- },
- ],
- },
- plugins: [
- new UiExtractPlugin({ context: paths.appSrc }),
- new OakWeChatMpPlugin({
- exclude: ['*/weui-miniprogram/*'],
- include: ['project.config.json', 'sitemap.json'],
- split: !isEnvDevelopment,
- }),
- new webpack.DefinePlugin(env.stringified),
- new StylelintPlugin({
- fix: true,
- files: '**/*.(sa|sc|le|wx|c)ss',
- }),
- new ProgressBarPlugin({
- summary: false,
- format: ':msg :percent (:elapsed seconds)',
- customSummary: (buildTime) =>
- console.log(
- chalk.gray(`\n[${new Date().toLocaleDateString()}`),
- chalk.green(`Compiled successfully!(${buildTime})\n`)
- ),
- }),
- new webpack.ProvidePlugin({
- Buffer: ['buffer', 'Buffer'],
- }),
- ].concat(
- copyPatterns.length > 0
- ? [
- new CopyWebpackPlugin({
- patterns: copyPatterns,
- }),
- ]
- : []
- ),
- watch: true,
- watchOptions: {
- aggregateTimeout: 600,
- ignored: '**/node_modules',
- followSymlinks: true,
- },
+ ],
+ },
+ ],
+ },
+ plugins: [
+ new UiExtractPlugin({ context: paths.appSrc }),
+ new OakWeChatMpPlugin({
+ exclude: ['*/weui-miniprogram/*'],
+ include: ['project.config.json', 'sitemap.json'],
+ split: !isEnvDevelopment,
+ }),
+ new webpack.DefinePlugin(env.stringified),
+ new StylelintPlugin({
+ fix: true,
+ files: '**/*.(sa|sc|le|wx|c)ss',
+ }),
+ new ProgressBarPlugin({
+ summary: false,
+ format: ':msg :percent (:elapsed seconds)',
+ customSummary: (buildTime) =>
+ console.log(
+ chalk.gray(`\n[${new Date().toLocaleDateString()}`),
+ chalk.green(`Compiled successfully!(${buildTime})\n`)
+ ),
+ }),
+ new webpack.ProvidePlugin({
+ Buffer: ['buffer', 'Buffer'],
+ }),
+ ].concat(
+ copyPatterns.length > 0
+ ? [
+ new CopyWebpackPlugin({
+ patterns: copyPatterns,
+ }),
+ ]
+ : []
+ ),
+ watch: true,
+ watchOptions: {
+ aggregateTimeout: 600,
+ ignored: '**/node_modules',
+ followSymlinks: true,
+ },
+ };
};
diff --git a/config/web/paths.js b/config/web/paths.js
index 7ddaffc..c0f368a 100644
--- a/config/web/paths.js
+++ b/config/web/paths.js
@@ -58,6 +58,7 @@ module.exports = {
appBuild: resolveApp(buildPath),
appPublic: resolveApp('public'),
appHtml: resolveApp('public/index.html'),
+ appIndexDevJs: resolveModule(resolveApp, 'src/index.dev'),
appIndexJs: resolveModule(resolveApp, 'src/index'),
appPackageJson: resolveRoot('package.json'),
appSrc: resolveApp('src'),
diff --git a/lib/build.js b/lib/build.js
index 8f2f37b..2ec7ade 100644
--- a/lib/build.js
+++ b/lib/build.js
@@ -7,12 +7,16 @@ const tip_style_1 = require("./tip-style");
const cross_spawn_1 = __importDefault(require("cross-spawn"));
async function build(cmd) {
if (!cmd.target) {
- (0, tip_style_1.Error)(`${(0, tip_style_1.error)(`Please add --target web or --target mp to he command`)}`);
+ (0, tip_style_1.Error)(`${(0, tip_style_1.error)(`Please add --target web or --target mp or --target wechatMp to he command`)}`);
return;
}
(0, tip_style_1.Success)(`${(0, tip_style_1.success)(`build ${cmd.target} environment: ${cmd.mode}`)}`);
- if (cmd.target === 'mp') {
- const result = cross_spawn_1.default.sync(`cross-env NODE_ENV=${cmd.mode} NODE_TARGET=${cmd.target} "${process.execPath}"`, [require.resolve('../scripts/build-mp.js')], {
+ if (cmd.target === 'mp' || cmd.target === 'wechatMp') {
+ const result = cross_spawn_1.default.sync(`cross-env NODE_ENV=${cmd.mode} NODE_TARGET=${cmd.target} "${process.execPath}"`, [
+ require.resolve(`../scripts/${cmd.mode === 'production'
+ ? 'build-mp.js'
+ : 'start-mp.js'}`),
+ ], {
stdio: 'inherit',
shell: true,
});
diff --git a/lib/file-handle.d.ts b/lib/file-handle.d.ts
index 50447af..0413e16 100644
--- a/lib/file-handle.d.ts
+++ b/lib/file-handle.d.ts
@@ -1,5 +1,4 @@
///
-///
import { PathLike } from 'fs';
import { checkFileExistsAndCreateType } from './enum';
/**
diff --git a/scripts/build-mp.js b/scripts/build-mp.js
index dfef3e2..d09acb1 100644
--- a/scripts/build-mp.js
+++ b/scripts/build-mp.js
@@ -2,13 +2,14 @@ require('../config/mp/env');
const webpack = require('webpack');
const chalk = require('chalk');
-const webpackConfig = require('../config/mp/webpack.config');
+const configFactory = require('../config/mp/webpack.config');
+const config = configFactory('production');
const paths = require('../config/mp/paths');
const getClientEnvironment = require('../config/mp/env');
const env = getClientEnvironment();
-webpack(webpackConfig, (err, stats) => {
+webpack(config, (err, stats) => {
if (err) {
console.log(chalk.red(err.stack || err));
if (err.details) {
diff --git a/scripts/start-mp.js b/scripts/start-mp.js
new file mode 100644
index 0000000..8e24fc6
--- /dev/null
+++ b/scripts/start-mp.js
@@ -0,0 +1,29 @@
+require('../config/mp/env');
+
+const webpack = require('webpack');
+const chalk = require('chalk');
+const configFactory = require('../config/mp/webpack.config');
+const config = configFactory('development');
+
+const paths = require('../config/mp/paths');
+const getClientEnvironment = require('../config/mp/env');
+const env = getClientEnvironment();
+
+webpack(config, (err, stats) => {
+ if (err) {
+ console.log(chalk.red(err.stack || err));
+ if (err.details) {
+ console.log(chalk.red(err.details));
+ }
+ return undefined;
+ }
+ if (stats) {
+ const info = stats.toJson();
+ if (stats.hasErrors()) {
+ info.errors.forEach((ele) => console.warn(ele));
+ }
+ if (stats.hasWarnings()) {
+ info.warnings.forEach((ele) => console.warn(ele));
+ }
+ }
+});
diff --git a/src/build.ts b/src/build.ts
index 3144bf2..e397456 100644
--- a/src/build.ts
+++ b/src/build.ts
@@ -12,15 +12,25 @@ import spawn from 'cross-spawn';
export default async function build(cmd: any) {
if (!cmd.target) {
Error(
- `${error(`Please add --target web or --target mp to he command`)}`
+ `${error(
+ `Please add --target web or --target mp or --target wechatMp to he command`
+ )}`
);
return;
}
Success(`${success(`build ${cmd.target} environment: ${cmd.mode}`)}`);
- if (cmd.target === 'mp') {
+ if (cmd.target === 'mp' || cmd.target === 'wechatMp') {
const result = spawn.sync(
`cross-env NODE_ENV=${cmd.mode} NODE_TARGET=${cmd.target} "${process.execPath}"`,
- [require.resolve('../scripts/build-mp.js')],
+ [
+ require.resolve(
+ `../scripts/${
+ cmd.mode === 'production'
+ ? 'build-mp.js'
+ : 'start-mp.js'
+ }`
+ ),
+ ],
{
stdio: 'inherit',
shell: true,