@moneko/core 3.1.0-beta.2 → 3.1.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1,33 @@
1
- import{readFileSync as e}from"fs";import o from"./paths.js";import t from"./yarn-argv.js";export const APPTYPE=process.env.APPTYPE;export const FRAMEWORK=process.env.FRAMEWORK;export const isLibrary="library"===APPTYPE;export const isMicro="micro"===APPTYPE;export const isReact="react"===FRAMEWORK;export const isSolid="solid"===FRAMEWORK;export const jsxImportSource={react:"react",solid:"solid-js/h"}[FRAMEWORK];export const createElement={react:"createElement",solid:"createComponent"}[FRAMEWORK];export const FRAMEWORKNAME={react:"react",solid:"solid-js"}[FRAMEWORK];export const PACKAGENAME=process.env.npm_package_name;export const PACKAGEVERSION=process.env.npm_package_version;let s=e(o.corePath,{encoding:"utf-8"});export const pkgName=JSON.parse(s).name;export const isDev="development"===process.env.NODE_ENV;export const CUSTOMCONFIG=process.env.npm_config_config||t.config;let n=Object.keys(process.env);export const hasEslintConfig=-1!==n.findIndex(e=>e.startsWith("npm_package_eslintConfig_"));export const hasStylelintConfig=-1!==n.findIndex(e=>e.startsWith("npm_package_stylelint_"));
1
+ import { readFileSync } from 'fs';
2
+ import paths from './paths.js';
3
+ import yarnArgv from './yarn-argv.js';
4
+ export const APPTYPE = process.env.APPTYPE;
5
+ export const FRAMEWORK = process.env.FRAMEWORK;
6
+ export const isLibrary = APPTYPE === 'library';
7
+ export const isMicro = APPTYPE === 'micro';
8
+ export const isReact = FRAMEWORK === 'react';
9
+ export const isSolid = FRAMEWORK === 'solid';
10
+ export const jsxImportSource = {
11
+ react: 'react',
12
+ solid: 'solid-js/h'
13
+ }[FRAMEWORK];
14
+ export const createElement = {
15
+ react: 'createElement',
16
+ solid: 'createComponent'
17
+ }[FRAMEWORK];
18
+ const frameworkMap = {
19
+ react: 'react',
20
+ solid: 'solid-js'
21
+ };
22
+ export const FRAMEWORKNAME = frameworkMap[FRAMEWORK];
23
+ export const PACKAGENAME = process.env.npm_package_name;
24
+ export const PACKAGEVERSION = process.env.npm_package_version;
25
+ const pkg = readFileSync(`${paths.corePath}/../package.json`, {
26
+ encoding: 'utf-8'
27
+ });
28
+ export const pkgName = JSON.parse(pkg).name;
29
+ export const isDev = process.env.NODE_ENV === 'development';
30
+ export const CUSTOMCONFIG = process.env.npm_config_config || yarnArgv.config;
31
+ const envKeys = Object.keys(process.env);
32
+ export const hasEslintConfig = envKeys.findIndex((k)=>k.startsWith('npm_package_eslintConfig_')) !== -1;
33
+ export const hasStylelintConfig = envKeys.findIndex((k)=>k.startsWith('npm_package_stylelint_')) !== -1;
package/lib/prod.js CHANGED
@@ -1,5 +1,64 @@
1
- import e from"css-minimizer-webpack-plugin";import i from"mini-css-extract-plugin";import n from"terser-webpack-plugin";import m from"webpack";import{BundleAnalyzerPlugin as o}from"webpack-bundle-analyzer";import{merge as r}from"webpack-merge";import{clientConfig as s}from"./common.js";import{CONFIG as t}from"./config.js";import{getMinifyOption as p}from"./minify.js";let{optimize:l}=m,{cssnanoMinify:u,swcMinify:c}=e,a="swc"===t.compiler,f=[];t.minifier&&(t.minifier.js&&f.push(new n(p(t.minifier.js?.type||(a?"swc":"terser"),t.minifier.js?.options))),t.minifier.css&&f.push(new e({minify:{swc:c,cssnano:u}[t.minifier.css?.type||(a?"swc":"cssnano")],minimizerOptions:t.minifier.css?.options})));let d={splitChunks:t.splitChunk,runtimeChunk:t.runtimeChunk,chunkIds:"named",moduleIds:"named",// parent chunk中解决了的chunk会被删除
2
- removeAvailableModules:!0,// 删除空的chunks
3
- removeEmptyChunks:!0,// 合并重复的chunk
4
- mergeDuplicateChunks:!0,minimize:!0,minimizer:f},k=r(s,{devtool:!1===t.devtool||t.devtool?t.devtool:"cheap-module-source-map",mode:"production",optimization:d,plugins:[// 压缩 css
5
- new i({filename:"style/[name].bundle.css",chunkFilename:"style/[name].chunk.css",experimentalUseImportModule:!0}),t.bundleAnalyzer&&new o(t.bundleAnalyzer),t.splitChunk&&new l.MinChunkSizePlugin({minChunkSize:1e4})].filter(Boolean)});export default[k];
1
+ import CssMinimizerPlugin from 'css-minimizer-webpack-plugin';
2
+ import MiniCssExtractPlugin from 'mini-css-extract-plugin';
3
+ import TerserPlugin from 'terser-webpack-plugin';
4
+ import webpack from 'webpack';
5
+ import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
6
+ import { merge } from 'webpack-merge';
7
+ import { clientConfig } from './common.js';
8
+ import { CONFIG } from './config.js';
9
+ import { getMinifyOption } from './minify.js';
10
+ const { optimize } = webpack;
11
+ const { cssnanoMinify, swcMinify } = CssMinimizerPlugin;
12
+ const swcCompiler = CONFIG.compiler === 'swc';
13
+ const defaultJsMiniify = swcCompiler ? 'swc' : 'terser';
14
+ const defaultCssMiniify = swcCompiler ? 'swc' : 'cssnano';
15
+ const cssMinify = {
16
+ swc: swcMinify,
17
+ cssnano: cssnanoMinify
18
+ };
19
+ const minimizer = [];
20
+ if (CONFIG.minifier) {
21
+ if (CONFIG.minifier.js) {
22
+ minimizer.push(new TerserPlugin(getMinifyOption(CONFIG.minifier.js?.type || defaultJsMiniify, CONFIG.minifier.js?.options)));
23
+ }
24
+ if (CONFIG.minifier.css) {
25
+ minimizer.push(new CssMinimizerPlugin({
26
+ minify: cssMinify[CONFIG.minifier.css?.type || defaultCssMiniify],
27
+ minimizerOptions: CONFIG.minifier.css?.options
28
+ }));
29
+ }
30
+ }
31
+ const optimization = {
32
+ splitChunks: CONFIG.splitChunk,
33
+ runtimeChunk: CONFIG.runtimeChunk,
34
+ chunkIds: 'named',
35
+ moduleIds: 'named',
36
+ // parent chunk中解决了的chunk会被删除
37
+ removeAvailableModules: true,
38
+ // 删除空的chunks
39
+ removeEmptyChunks: true,
40
+ // 合并重复的chunk
41
+ mergeDuplicateChunks: true,
42
+ minimize: true,
43
+ minimizer: minimizer
44
+ };
45
+ const client = merge(clientConfig, {
46
+ devtool: CONFIG.devtool === false || CONFIG.devtool ? CONFIG.devtool : 'cheap-module-source-map',
47
+ mode: 'production',
48
+ optimization: optimization,
49
+ plugins: [
50
+ // 压缩 css
51
+ new MiniCssExtractPlugin({
52
+ filename: 'style/[name].bundle.css',
53
+ chunkFilename: 'style/[name].chunk.css',
54
+ experimentalUseImportModule: true
55
+ }),
56
+ CONFIG.bundleAnalyzer && new BundleAnalyzerPlugin(CONFIG.bundleAnalyzer),
57
+ CONFIG.splitChunk && new optimize.MinChunkSizePlugin({
58
+ minChunkSize: 10000
59
+ })
60
+ ].filter(Boolean)
61
+ });
62
+ export default [
63
+ client
64
+ ];
package/lib/rem.js CHANGED
@@ -1 +1,6 @@
1
- import{CONFIG as e}from"./config.js";let t="";e.rem.designSize&&(t=`!function(e,n){function t(){let n=e.documentElement,t=n.clientWidth||e.body.clientWidth,i=t<=375?375:${e.rem.designSize},o=t;o=t<=375?t:t<=${e.rem.designSize}?i:t;let d=16/i*o+"px";d!==n.style.fontSize&&(n.style.fontSize=d)}t(),"addEventListener"in e&&n.addEventListener("orientationchange"in n?"orientationchange":"resize",t,!1)}(document,window);`);export default t;
1
+ import { CONFIG } from './config.js';
2
+ let rem = '';
3
+ if (CONFIG.rem.designSize) {
4
+ rem = `!function(e,n){function t(){let n=e.documentElement,t=n.clientWidth||e.body.clientWidth,i=t<=375?375:${CONFIG.rem.designSize},o=t;o=t<=375?t:t<=${CONFIG.rem.designSize}?i:t;let d=16/i*o+"px";d!==n.style.fontSize&&(n.style.fontSize=d)}t(),"addEventListener"in e&&n.addEventListener("orientationchange"in n?"orientationchange":"resize",t,!1)}(document,window);`;
5
+ }
6
+ export default rem;
@@ -1 +1,27 @@
1
- import*as e from"fs";import s from"enhanced-resolve";let{CachedInputFileSystem:o,ResolverFactory:n}=s,m=n.createResolver({fileSystem:new o(e,4e3),conditionNames:["node"],extensions:[".js",".json",".node"],useSyncFileSystemCalls:!0,mainFields:["esm","module","main"]});export default m;
1
+ import * as fs from 'fs';
2
+ import enhancedResolve from 'enhanced-resolve';
3
+ const { CachedInputFileSystem, ResolverFactory } = enhancedResolve;
4
+ /**
5
+ * @examples
6
+ * ```javascript
7
+ * // 获取 react 包入口路径,优先 esm,兜底 cjs
8
+ * resolverSync.resolveSync({}, process.cwd(), "react")
9
+ * ```
10
+ */ const resolverSync = ResolverFactory.createResolver({
11
+ fileSystem: new CachedInputFileSystem(fs, 4000),
12
+ conditionNames: [
13
+ 'node'
14
+ ],
15
+ extensions: [
16
+ '.js',
17
+ '.json',
18
+ '.node'
19
+ ],
20
+ useSyncFileSystemCalls: true,
21
+ mainFields: [
22
+ 'esm',
23
+ 'module',
24
+ 'main'
25
+ ]
26
+ });
27
+ export default resolverSync;
package/lib/routes.js CHANGED
@@ -1,4 +1,209 @@
1
- let e,t;import{readFileSync as r,readdirSync as o,statSync as n}from"fs";import{join as s,relative as a}from"path";import{watch as i}from"chokidar";import{load as p}from"js-yaml";import{hasCustomRouter as l}from"./config.js";import c from"./object-listener.js";import m from"./paths.js";import{FRAMEWORK as u,FRAMEWORKNAME as f,createElement as d,isLibrary as g,isReact as h,isSolid as x}from"./process-env.js";let $=/^---\n([\s\S]+?)\n---\n/,j=x?"component":"element";function O(e){return e.replace(/\$/g,":").replace(/^index\.tsx?$/,"/").replace(/^README\.mdx?$/,"/")}function b(e,t){let{regex:i,alia:l,base:c=e,outputSource:m}=t,u=o(e);return u.reduce((o,u)=>{let f=s(e,u),d=n(f);if(d.isDirectory()){let e=b(f,{...t,base:c});if(e.length>0){let t={},r={path:O(u),key:O(a(c,f))};if(m)Object.assign(t,{children:e});else{let o=e.findIndex(e=>"/"===e.path||r.path===e.path),n=e.splice(o,1)[0];e.length?Object.assign(t,!x&&n,{children:[x&&{...n,path:r.path===n.path?"/":n.path},...e].filter(Boolean)}):Object.assign(t,n)}o.push(Object.assign(t,r))}}else if(i.test(f)){let e=r(f,{encoding:"utf-8"}),t=function(e){let t=e.match($);return t&&t[1]?t[1].trim():null}(e),n=t?p(t):{},i=a(c,f),u=O(i);o.push(Object.assign({path:u.split("/").slice(-2,-1)?.join("")||"/",key:u.replace(/\/?index.tsx?$/,"/").replace(/\/?README.mdx?$/,"/").split("/").filter(Boolean).join("/"),meta:{...n}},l&&{[j]:`rr(() => import(/* webpackChunkName: '${i}' */'${s(l,i)}'))rr`},m&&{codes:function(e){let t;let r={},o=/```(.+?)\n([\s\S]*?)\n```/g;for(;null!==(t=o.exec(e));){let[,e="jsx",o]=t,n=e.split(" ").pop()||"jsx";r[n]=o.trim()}return Object.keys(r).length?r:{jsx:e}}(e.replace($,"").replace(/^\n+|\n+$/g,""))}))}return o},[])}export const route=c({name:"@app/routes",data:"export default []"});export const example=c({name:"@app/example",data:{}});let y=`${x?"() => ":""}${d}(SuspenseComp, { comp: $1 })`,T=`import { ${d} } from "${f}";import SuspenseComp from "@app/suspense";${h?'import prefix from "@app/prefix-router";':""}`;l&&(T+='import merge from "@app/merge-router";import customRouter from "@/router";'),["react","solid"].includes(u)||(y="$1",T="");export let routes=[];function k(e){return`${T}const routes = [{ path: "/", children: [${x?'{ path: "/" },':""} ${e}] }];const _routes = ${l?'merge([...routes, ...customRouter], "path")':"routes"};export default ${h?"prefix(_routes)":"_routes"};`}function E(e,t,r){let o=i(e,{ignored:(e,r)=>{if(r)return!r?.isDirectory()&&t.test(e)},persistent:!0,ignoreInitial:!1});o.on("add",()=>{r()}).on("change",()=>{r()}).on("unlink",()=>{r()}),process.on("SIGINT",function(){o.close()})}g?(// router
2
- E(m.componentsPath,/(?<!README\.mdx?)$/,function(){clearTimeout(e),e=setTimeout(()=>{clearTimeout(e),routes=b(m.componentsPath,{regex:/README\.mdx?$/,alia:"@pkg"});let t=JSON.stringify(routes).replace(/"rr\((.+?)\)rr"/g,y).slice(1,-1);Object.assign(route.data,{data:k(t)})},100)}),// demos
3
- E(m.componentsPath,/(?<!\/examples\/(.+)\.md)$/,function(){clearTimeout(t),t=setTimeout(()=>{clearTimeout(t);let e={};b(m.componentsPath,{regex:/\/examples\/(.+)\.md$/,outputSource:!0}).forEach(t=>{let r=[example.data.name,t.key].filter(Boolean).join("/"),o=t.children?.[0].children?.filter(e=>e.codes)?.map(e=>({title:e.path.replace(/.md$/,""),order:0,...e.meta,codes:e.codes})).sort((e,t)=>e.order-t.order);Object.assign(e,{[r]:`export default ${JSON.stringify(o)};`})}),Object.assign(example.data,{data:e})},100)})):// router
4
- E(m.pagesPath,/(?<!index\.tsx?)$/,function(){clearTimeout(e),e=setTimeout(()=>{clearTimeout(e),routes=b(m.pagesPath,{regex:/index\.tsx?$/,alia:"@/pages"});let t=JSON.stringify(routes).replace(/"rr\((.+?)\)rr"/g,y).slice(1,-1);Object.assign(route.data,{data:k(t)})},100)});
1
+ import { readFileSync, readdirSync, statSync } from 'fs';
2
+ import { join, relative } from 'path';
3
+ import { watch } from 'chokidar';
4
+ import { load } from 'js-yaml';
5
+ import { hasCustomRouter } from './config.js';
6
+ import objectListener from './object-listener.js';
7
+ import paths from './paths.js';
8
+ import { FRAMEWORK, FRAMEWORKNAME, createElement, isLibrary, isReact, isSolid } from './process-env.js';
9
+ const frontmatterRegex = /^---\n([\s\S]+?)\n---\n/;
10
+ function extractFrontmatter(md) {
11
+ const matches = md.match(frontmatterRegex);
12
+ return matches && matches[1] ? matches[1].trim() : null;
13
+ }
14
+ const elename = isSolid ? 'component' : 'element';
15
+ function extractCode(codeStr) {
16
+ const codes = {};
17
+ const regex = /```(.+?)\n([\s\S]*?)\n```/g;
18
+ let match;
19
+ while((match = regex.exec(codeStr)) !== null){
20
+ const [, language = 'jsx', source] = match;
21
+ const lang = language.split(' ').pop() || 'jsx';
22
+ codes[lang] = source.trim();
23
+ }
24
+ return Object.keys(codes).length ? codes : {
25
+ jsx: codeStr
26
+ };
27
+ }
28
+ function prefixPath(src) {
29
+ return src.replace(/\$/g, ':').replace(/^index\.tsx?$/, '/').replace(/^README\.mdx?$/, '/');
30
+ }
31
+ function getTree(directory, option) {
32
+ const { regex, alia, base = directory, outputSource } = option;
33
+ const files = readdirSync(directory);
34
+ return files.reduce((tree, file)=>{
35
+ const filePath = join(directory, file);
36
+ const stats = statSync(filePath);
37
+ if (stats.isDirectory()) {
38
+ const children = getTree(filePath, {
39
+ ...option,
40
+ base
41
+ });
42
+ if (children.length > 0) {
43
+ const item = {};
44
+ const baseItem = {
45
+ path: prefixPath(file),
46
+ key: prefixPath(relative(base, filePath))
47
+ };
48
+ if (outputSource) {
49
+ Object.assign(item, {
50
+ children
51
+ });
52
+ } else {
53
+ const baseIdx = children.findIndex((c)=>c.path === '/' || baseItem.path === c.path);
54
+ const frist = children.splice(baseIdx, 1)[0];
55
+ if (children.length) {
56
+ Object.assign(item, !isSolid && frist, {
57
+ children: [
58
+ isSolid && {
59
+ ...frist,
60
+ path: baseItem.path === frist.path ? '/' : frist.path
61
+ },
62
+ ...children
63
+ ].filter(Boolean)
64
+ });
65
+ } else {
66
+ Object.assign(item, frist);
67
+ }
68
+ }
69
+ tree.push(Object.assign(item, baseItem));
70
+ }
71
+ } else if (regex.test(filePath)) {
72
+ const source = readFileSync(filePath, {
73
+ encoding: 'utf-8'
74
+ });
75
+ const frontmatter = extractFrontmatter(source);
76
+ const meta = frontmatter ? load(frontmatter) : {};
77
+ const reslove = relative(base, filePath);
78
+ const realPath = prefixPath(reslove);
79
+ tree.push(Object.assign({
80
+ path: realPath.split('/').slice(-2, -1)?.join('') || '/',
81
+ key: realPath.replace(/\/?index.tsx?$/, '/').replace(/\/?README.mdx?$/, '/').split('/').filter(Boolean).join('/'),
82
+ meta: {
83
+ ...meta
84
+ }
85
+ }, alia && {
86
+ [elename]: `rr(() => import(/* webpackChunkName: '${reslove}' */'${join(alia, reslove)}'))rr`
87
+ }, outputSource && {
88
+ codes: extractCode(source.replace(frontmatterRegex, '').replace(/^\n+|\n+$/g, ''))
89
+ }));
90
+ }
91
+ return tree;
92
+ }, []);
93
+ }
94
+ export const route = objectListener({
95
+ name: '@app/routes',
96
+ data: 'export default []'
97
+ });
98
+ export const example = objectListener({
99
+ name: '@app/example',
100
+ data: {}
101
+ });
102
+ let replaceStr = `${isSolid ? '() => ' : ''}${createElement}(SuspenseComp, { comp: $1 })`;
103
+ let prefixStr = `import { ${createElement} } from "${FRAMEWORKNAME}";import SuspenseComp from "@app/suspense";${isReact ? 'import prefix from "@app/prefix-router";' : ''}`;
104
+ if (hasCustomRouter) {
105
+ prefixStr += 'import merge from "@app/merge-router";import customRouter from "@/router";';
106
+ }
107
+ if (![
108
+ 'react',
109
+ 'solid'
110
+ ].includes(FRAMEWORK)) {
111
+ replaceStr = '$1';
112
+ prefixStr = '';
113
+ }
114
+ export let routes = [];
115
+ let timerRoutes;
116
+ function updateData(tree) {
117
+ return `${prefixStr}const routes = [{ path: "/", children: [${isSolid ? '{ path: "/" },' : ''} ${tree}] }];const _routes = ${hasCustomRouter ? 'merge([...routes, ...customRouter], "path")' : 'routes'};export default ${isReact ? 'prefix(_routes)' : '_routes'};`;
118
+ }
119
+ function generatorLibraryRouter() {
120
+ clearTimeout(timerRoutes);
121
+ timerRoutes = setTimeout(()=>{
122
+ clearTimeout(timerRoutes);
123
+ routes = getTree(paths.componentsPath, {
124
+ regex: /README\.mdx?$/,
125
+ alia: '@pkg'
126
+ });
127
+ const tree = JSON.stringify(routes).replace(/"rr\((.+?)\)rr"/g, replaceStr).slice(1, -1);
128
+ Object.assign(route.data, {
129
+ data: updateData(tree)
130
+ });
131
+ }, 100);
132
+ }
133
+ let timerExample;
134
+ function generatorLibraryDemo() {
135
+ clearTimeout(timerExample);
136
+ timerExample = setTimeout(()=>{
137
+ clearTimeout(timerExample);
138
+ const exampleNext = {};
139
+ getTree(paths.componentsPath, {
140
+ regex: /\/examples\/(.+)\.md$/,
141
+ outputSource: true
142
+ }).forEach((item)=>{
143
+ const _name = [
144
+ example.data.name,
145
+ item.key
146
+ ].filter(Boolean).join('/');
147
+ const data = item.children?.[0].children?.filter((e)=>e.codes)?.map((e)=>({
148
+ title: e.path.replace(/.md$/, ''),
149
+ order: 0,
150
+ ...e.meta,
151
+ codes: e.codes
152
+ })).sort((a, b)=>a.order - b.order);
153
+ Object.assign(exampleNext, {
154
+ [_name]: `export default ${JSON.stringify(data)};`
155
+ });
156
+ });
157
+ Object.assign(example.data, {
158
+ data: exampleNext
159
+ });
160
+ }, 100);
161
+ }
162
+ function watchFiles(root, ignored, call) {
163
+ const ignoredRouter = (src, stats)=>{
164
+ if (stats) {
165
+ if (stats?.isDirectory()) {
166
+ return false;
167
+ }
168
+ return ignored.test(src);
169
+ }
170
+ };
171
+ const watcher = watch(root, {
172
+ ignored: ignoredRouter,
173
+ persistent: true,
174
+ ignoreInitial: false
175
+ });
176
+ watcher.on('add', ()=>{
177
+ call();
178
+ }).on('change', ()=>{
179
+ call();
180
+ }).on('unlink', ()=>{
181
+ call();
182
+ });
183
+ process.on('SIGINT', function() {
184
+ watcher.close();
185
+ });
186
+ }
187
+ function generatorRouter() {
188
+ clearTimeout(timerRoutes);
189
+ timerRoutes = setTimeout(()=>{
190
+ clearTimeout(timerRoutes);
191
+ routes = getTree(paths.pagesPath, {
192
+ regex: /index\.tsx?$/,
193
+ alia: '@/pages'
194
+ });
195
+ const tree = JSON.stringify(routes).replace(/"rr\((.+?)\)rr"/g, replaceStr).slice(1, -1);
196
+ Object.assign(route.data, {
197
+ data: updateData(tree)
198
+ });
199
+ }, 100);
200
+ }
201
+ if (isLibrary) {
202
+ // router
203
+ watchFiles(paths.componentsPath, /(?<!README\.mdx?)$/, generatorLibraryRouter);
204
+ // demos
205
+ watchFiles(paths.componentsPath, /(?<!\/examples\/(.+)\.md)$/, generatorLibraryDemo);
206
+ } else {
207
+ // router
208
+ watchFiles(paths.pagesPath, /(?<!index\.tsx?)$/, generatorRouter);
209
+ }
package/lib/seo.js CHANGED
@@ -1,2 +1,41 @@
1
- import{existsSync as t,mkdirSync as o,writeFileSync as r}from"fs";import{join as m}from"path";import{outputConfig as s}from"./common.js";import{CONFIG as i}from"./config.js";import e from"./paths.js";import{routes as p}from"./routes.js";import{resolveProgramPath as n}from"./utils.js";function a(t,o){try{r(t,o,"utf-8")}catch(t){//
2
- }}export const seo=()=>{let{domain:r,nojekyll:f,path:h}=i.seo||{};if(!r)return;let c=i.basename,l=c.endsWith("/")?c:`${c}/`,j=h&&n(h)||s?.path||e.programPath;t(j)||o(j),a(m(j,"CNAME"),r),a(m(j,"robots"),`Sitemap: https://${r}${l}sitemap.txt`);let u=[];!function t(o){o.forEach(o=>{u.push(`https://${r}${l}${o.key}`),Array.isArray(o.children)&&t(o.children)})}(p),a(m(j,"sitemap.txt"),u.join("\n")),f&&a(m(j,".nojekyll"),"")};
1
+ import { existsSync, mkdirSync, writeFileSync } from 'fs';
2
+ import { join } from 'path';
3
+ import { outputConfig } from './common.js';
4
+ import { CONFIG } from './config.js';
5
+ import { routes } from './routes.js';
6
+ import { resolveProgramPath } from './utils.js';
7
+ function writeFile(path, data) {
8
+ try {
9
+ writeFileSync(path, data, 'utf-8');
10
+ } catch (error) {
11
+ //
12
+ }
13
+ }
14
+ export const seo = ()=>{
15
+ const { domain, nojekyll, path } = CONFIG.seo || {};
16
+ const baseDir = path && resolveProgramPath(path) || outputConfig?.path;
17
+ if (!domain || !baseDir) {
18
+ return;
19
+ }
20
+ if (!existsSync(baseDir)) {
21
+ mkdirSync(baseDir);
22
+ }
23
+ const routeBase = CONFIG.basename;
24
+ const base = routeBase.endsWith('/') ? routeBase : `${routeBase}/`;
25
+ writeFile(join(baseDir, 'CNAME'), domain);
26
+ writeFile(join(baseDir, 'robots'), `Sitemap: https://${domain}${base}sitemap.txt`);
27
+ const sitemap = [];
28
+ function getSiteMap(list) {
29
+ list.forEach((item)=>{
30
+ sitemap.push(`https://${domain}${base}${item.key}`);
31
+ if (Array.isArray(item.children)) {
32
+ getSiteMap(item.children);
33
+ }
34
+ });
35
+ }
36
+ getSiteMap(routes);
37
+ writeFile(join(baseDir, 'sitemap.txt'), sitemap.join('\n'));
38
+ if (nojekyll) {
39
+ writeFile(join(baseDir, '.nojekyll'), '');
40
+ }
41
+ };
package/lib/swcrc.js CHANGED
@@ -1,2 +1,107 @@
1
- import{merge as e}from"webpack-merge";import{CONFIG as o}from"./config.js";import r from"./paths.js";import{isReact as t,isSolid as s,jsxImportSource as n}from"./process-env.js";// swc polyfill 策略,会复用 babel 链路,但效率比 babel 低
2
- let a={env:{targets:[">0.3%","defaults","supports es6-module","maintained node versions"],mode:"entry",coreJs:"3"}};export const swcMinifyOption={compress:{top_retain:[],keep_infinity:!0,global_defs:{"@alert":"console.log"},pure_funcs:["console.log","console.warn","console.error","console.info"],toplevel:!1,drop_console:!0,drop_debugger:!0,module:!1,ecma:2015,ie8:!1,keep_classnames:void 0,keep_fnames:!1},mangle:!0};export default((p=!1)=>{let c={module:{type:"es6",resolveFully:!0},jsc:{parser:{syntax:"typescript",decorators:!0,dynamicImport:!0,tsx:!0,topLevelAwait:!0,importMeta:!0},loose:!0,target:"es2022",externalHelpers:!0,transform:{legacyDecorator:!0,decoratorMetadata:!0,react:{runtime:"automatic",throwIfNamespace:!0,useBuiltins:!0,refresh:t&&p,development:p,importSource:n},optimizer:{simplify:!1}},experimental:{emitAssertForImportAttributes:!0,cacheRoot:r.swcCachePath,plugins:[["swc-plugin-another-transform-imports",function(e){for(let o=0,r=Object.keys(e),t=r.length;o<t;o++)e[r[o]].transform=`${r[o]}/${e[r[o]].transform}`,e[r[o]].style&&(e[r[o]].style=`${r[o]}/${e[r[o]].style}`);return e}(o.importOnDemand||{})],s&&["@moneko/jsx-dom-expressions",o.jsxDomExpressions||{}]].filter(Boolean)}},sourceMaps:!0,parseMap:!0},i=Object.assign(c,!p&&a);return o.swcrc&&(i=e(i,"function"==typeof o.swcrc?o.swcrc(p):o.swcrc)),i});
1
+ import { merge } from 'webpack-merge';
2
+ import { CONFIG } from './config.js';
3
+ import paths from './paths.js';
4
+ import { isReact, isSolid, jsxImportSource } from './process-env.js';
5
+ // swc polyfill 策略,会复用 babel 链路,但效率比 babel 低
6
+ const swcPolyfill = {
7
+ env: {
8
+ targets: [
9
+ '>0.3%',
10
+ 'defaults',
11
+ 'supports es6-module',
12
+ 'maintained node versions'
13
+ ],
14
+ mode: 'entry',
15
+ coreJs: '3'
16
+ }
17
+ };
18
+ export const swcMinifyOption = {
19
+ compress: {
20
+ top_retain: [],
21
+ keep_infinity: true,
22
+ global_defs: {
23
+ '@alert': 'console.log'
24
+ },
25
+ pure_funcs: [
26
+ 'console.log',
27
+ 'console.warn',
28
+ 'console.error',
29
+ 'console.info'
30
+ ],
31
+ toplevel: false,
32
+ drop_console: true,
33
+ drop_debugger: true,
34
+ module: false,
35
+ ecma: 2015,
36
+ ie8: false,
37
+ keep_classnames: void 0,
38
+ keep_fnames: false
39
+ },
40
+ mangle: true
41
+ };
42
+ function transformConfigs(config) {
43
+ for(let i = 0, ks = Object.keys(config), l = ks.length; i < l; i++){
44
+ config[ks[i]].transform = `${ks[i]}/${config[ks[i]].transform}`;
45
+ if (config[ks[i]].style) {
46
+ config[ks[i]].style = `${ks[i]}/${config[ks[i]].style}`;
47
+ }
48
+ }
49
+ return config;
50
+ }
51
+ export default ((isDev = false)=>{
52
+ const swcOption = {
53
+ module: {
54
+ type: 'es6',
55
+ resolveFully: true
56
+ },
57
+ jsc: {
58
+ parser: {
59
+ syntax: 'typescript',
60
+ decorators: true,
61
+ dynamicImport: true,
62
+ tsx: true,
63
+ topLevelAwait: true,
64
+ importMeta: true
65
+ },
66
+ loose: true,
67
+ target: 'es2022',
68
+ externalHelpers: true,
69
+ transform: {
70
+ legacyDecorator: true,
71
+ decoratorMetadata: true,
72
+ react: {
73
+ runtime: 'automatic',
74
+ throwIfNamespace: true,
75
+ useBuiltins: true,
76
+ refresh: isReact && isDev,
77
+ development: isDev,
78
+ importSource: jsxImportSource
79
+ },
80
+ optimizer: {
81
+ simplify: false
82
+ }
83
+ },
84
+ experimental: {
85
+ emitAssertForImportAttributes: true,
86
+ cacheRoot: paths.swcCachePath,
87
+ plugins: [
88
+ [
89
+ 'swc-plugin-another-transform-imports',
90
+ transformConfigs(CONFIG.importOnDemand || {})
91
+ ],
92
+ isSolid && [
93
+ '@moneko/jsx-dom-expressions',
94
+ CONFIG.jsxDomExpressions || {}
95
+ ]
96
+ ].filter(Boolean)
97
+ }
98
+ },
99
+ sourceMaps: true,
100
+ parseMap: true
101
+ };
102
+ let swcrc = Object.assign(swcOption, !isDev && swcPolyfill);
103
+ if (CONFIG.swcrc) {
104
+ swcrc = merge(swcrc, typeof CONFIG.swcrc === 'function' ? CONFIG.swcrc(isDev) : CONFIG.swcrc);
105
+ }
106
+ return swcrc;
107
+ });
@@ -1,2 +1,26 @@
1
- import t from"fs";import r from"ts-import-plugin";import o from"webpack-merge";import{CONFIG as e}from"./config.js";import{isFunction as s,readConf as m,resolveProgramPath as a}from"./utils.js";let i=[];Array.isArray(e.importOnDemand)&&Object.assign(i,e.importOnDemand.map(t=>r(t)));let n=[...i],p={transpileOnly:!0,getCustomTransformers:()=>({before:n})};try{let r=a("tsloader.config.ts");t.accessSync(r,t.constants.R_OK);let e=(await m(r,"tsloader.config")).default;p=o(p,s(e)?e(process):e);// eslint-disable-next-line no-empty
2
- }catch(t){}export default p;
1
+ import fs from 'fs';
2
+ import transformerFactory from 'ts-import-plugin';
3
+ import merge from 'webpack-merge';
4
+ import { CONFIG } from './config.js';
5
+ import { isFunction, readConf, resolveProgramPath } from './utils.js';
6
+ const importOnDemand = [];
7
+ if (Array.isArray(CONFIG.importOnDemand)) {
8
+ Object.assign(importOnDemand, CONFIG.importOnDemand.map((item)=>transformerFactory(item)));
9
+ }
10
+ const beforeTransformers = [
11
+ ...importOnDemand
12
+ ];
13
+ let tsLoaderConfig = {
14
+ transpileOnly: true,
15
+ getCustomTransformers: ()=>({
16
+ before: beforeTransformers
17
+ })
18
+ };
19
+ try {
20
+ const customTsloaderConfigPath = resolveProgramPath('tsloader.config.ts');
21
+ fs.accessSync(customTsloaderConfigPath, fs.constants.R_OK);
22
+ const customTsloaderConfig = (await readConf(customTsloaderConfigPath, 'tsloader.config')).default;
23
+ tsLoaderConfig = merge(tsLoaderConfig, isFunction(customTsloaderConfig) ? customTsloaderConfig(process) : customTsloaderConfig);
24
+ // eslint-disable-next-line no-empty
25
+ } catch (error) {}
26
+ export default tsLoaderConfig;
package/lib/utils.js CHANGED
@@ -1,14 +1,76 @@
1
- import{readFileSync as t,writeFileSync as e}from"fs";import{resolve as o}from"path";import{transformFileSync as r}from"@swc/core";import n from"./paths.js";import c from"./resolver-sync.js";let s=/export\s+(?:async\s+)?(?:function|const)\s+(\w+)/g;/** 获取导出标识
1
+ import { readFileSync, writeFileSync } from 'fs';
2
+ import { resolve } from 'path';
3
+ import { transformFileSync } from '@swc/core';
4
+ import paths from './paths.js';
5
+ import resolverSync from './resolver-sync.js';
6
+ const exportPattern = /export\s+(?:async\s+)?(?:function|const)\s+(\w+)/g;
7
+ /** 获取导出标识
2
8
  * @param {string} path 文件地址
3
9
  * @returns {string[]} 包含的标识
4
- */export function getExportTokens(e){let o;let r=t(e,{encoding:"utf-8"}),n=[];for(;o=s.exec(r);)n.includes(o[1])||n.push(o[1]);return n}let p={inputSourceMap:!1,sourceMaps:!1,module:{type:"es6"},jsc:{parser:{syntax:"typescript"},loose:!1}};export function tfc(t){return r(t,p).code||"{}"}export function readConf(t,o){let r=`${n.cachePath}/${o}.mjs`;return e(r,tfc(t),"utf-8"),import(r)}export function toUpperCaseString(t){return t?.replace(/\b\w/g,t=>t.toUpperCase()).replace(/\./g," ")}/** 位于项目根目录下的位置
10
+ */ export function getExportTokens(path) {
11
+ const code = readFileSync(path, {
12
+ encoding: 'utf-8'
13
+ });
14
+ const tokens = [];
15
+ let match;
16
+ while(match = exportPattern.exec(code)){
17
+ if (!tokens.includes(match[1])) {
18
+ tokens.push(match[1]);
19
+ }
20
+ }
21
+ return tokens;
22
+ }
23
+ const swcOption = {
24
+ inputSourceMap: false,
25
+ sourceMaps: false,
26
+ module: {
27
+ type: 'es6'
28
+ },
29
+ jsc: {
30
+ parser: {
31
+ syntax: 'typescript'
32
+ },
33
+ loose: false
34
+ }
35
+ };
36
+ export function tfc(filepath) {
37
+ return transformFileSync(filepath, swcOption).code || '{}';
38
+ }
39
+ export function readConf(src, name) {
40
+ const cacheFile = `${paths.cachePath}/${name}.mjs`;
41
+ writeFileSync(cacheFile, tfc(src), 'utf-8');
42
+ return import(cacheFile);
43
+ }
44
+ export function toUpperCaseString(string) {
45
+ return string?.replace(/\b\w/g, (th)=>th.toUpperCase()).replace(/\./g, ' ');
46
+ }
47
+ /** 位于项目根目录下的位置
5
48
  * @param {string} src 路径
6
49
  * @returns {string} 位于项目根目录下的位置
7
- */export function resolveProgramPath(t){return o(n.programPath,`./${t}`)}/** 位于项目根目录node_modules下的位置
50
+ */ export function resolveProgramPath(src) {
51
+ return resolve(paths.programPath, `./${src}`);
52
+ }
53
+ /** 位于项目根目录node_modules下的位置
8
54
  * @param {string} src 路径
9
55
  * @returns {string} 位于项目根目录node_modules下的位置
10
- */export const resolveNodeModulesPath=t=>resolveProgramPath(`node_modules/${t}`);/** 获取模块真实入口位置
56
+ */ export const resolveNodeModulesPath = (src)=>{
57
+ return resolveProgramPath(`node_modules/${src}`);
58
+ };
59
+ /** 获取模块真实入口位置
11
60
  * @param {string} url 路径
12
61
  * @returns {string} 模块真实入口路径
13
- */export const realResolve=t=>c.resolveSync({},n.programPath,t)||t;export function isObject(t){let e=typeof t;return null!==t&&("object"==e||"function"==e)}// eslint-disable-next-line no-unused-vars
14
- export function isFunction(t){if(!isObject(t))return!1;let e=Object.prototype.toString.call(t);return"[object Function]"==e||"[object AsyncFunction]"==e||"[object GeneratorFunction]"==e||"[object Proxy]"==e}
62
+ */ export const realResolve = (url)=>resolverSync.resolveSync({}, paths.programPath, url) || url;
63
+ const funcTag = '[object Function]';
64
+ const asyncTag = '[object AsyncFunction]';
65
+ const genTag = '[object GeneratorFunction]';
66
+ const proxyTag = '[object Proxy]';
67
+ export function isObject(target) {
68
+ const type = typeof target;
69
+ return target !== null && (type == 'object' || type == 'function');
70
+ }
71
+ // eslint-disable-next-line no-unused-vars
72
+ export function isFunction(target) {
73
+ if (!isObject(target)) return false;
74
+ const tagType = Object.prototype.toString.call(target);
75
+ return tagType == funcTag || tagType == asyncTag || tagType == genTag || tagType == proxyTag;
76
+ }