@unsetsoft/ryunix-presets 0.0.6 → 1.0.14
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.
- package/package.json +55 -7
- package/rspack/index.js +92 -92
- package/vite/index.js +18 -18
- package/webpack/bin/compiler.mjs +6 -0
- package/webpack/bin/index.mjs +115 -0
- package/webpack/bin/prerender.mjs +138 -0
- package/webpack/bin/serve.mjs +101 -0
- package/webpack/config.d.ts +85 -0
- package/webpack/eslint.config.mjs +31 -0
- package/webpack/index.js +6 -0
- package/webpack/template/index.html +19 -0
- package/webpack/utils/config.cjs +190 -0
- package/webpack/utils/envExist.cjs +14 -0
- package/webpack/utils/index.mjs +203 -0
- package/webpack/utils/settingfile.cjs +33 -0
- package/webpack/webpack.config.mjs +279 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unsetsoft/ryunix-presets",
|
|
3
3
|
"description": "Package with presets for different development environments.",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "1.0.14",
|
|
5
5
|
"author": "Neyunse",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"repository": "https://github.com/UnSetSoft/Ryunixjs",
|
|
@@ -11,18 +11,66 @@
|
|
|
11
11
|
],
|
|
12
12
|
"files": [
|
|
13
13
|
"vite/",
|
|
14
|
-
"rspack/"
|
|
14
|
+
"rspack/",
|
|
15
|
+
"webpack/"
|
|
15
16
|
],
|
|
16
|
-
"
|
|
17
|
-
|
|
17
|
+
"peerDependencies": {
|
|
18
|
+
"@unsetsoft/ryunixjs": "^1.2.1"
|
|
19
|
+
},
|
|
18
20
|
"publishConfig": {
|
|
19
21
|
"registry": "https://registry.npmjs.org"
|
|
20
22
|
},
|
|
21
23
|
"exports": {
|
|
22
24
|
"./vite": "./vite/index.js",
|
|
23
|
-
"./rspack": "./rspack/index.js"
|
|
25
|
+
"./rspack": "./rspack/index.js",
|
|
26
|
+
"./webpack": "./webpack/index.js"
|
|
27
|
+
},
|
|
28
|
+
"types": "./webpack/config.d.ts",
|
|
29
|
+
"bin": {
|
|
30
|
+
"ryunix": "./webpack/bin/index.mjs"
|
|
24
31
|
},
|
|
25
32
|
"engines": {
|
|
26
|
-
"node": "^18 || ^22"
|
|
33
|
+
"node": "^18 || ^20 || ^22"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@babel/cli": "7.27.2",
|
|
37
|
+
"@babel/core": "7.27.4",
|
|
38
|
+
"@babel/plugin-proposal-class-properties": "7.18.6",
|
|
39
|
+
"@babel/plugin-transform-react-jsx": "7.27.1",
|
|
40
|
+
"@babel/preset-env": "7.27.2",
|
|
41
|
+
"@babel/preset-react": "7.27.1",
|
|
42
|
+
"@eslint/eslintrc": "3.3.1",
|
|
43
|
+
"@eslint/js": "9.31.0",
|
|
44
|
+
"@rollup/plugin-terser": "0.4.4",
|
|
45
|
+
"@swc/core": "1.12.6",
|
|
46
|
+
"babel-loader": "10.0.0",
|
|
47
|
+
"chalk": "5.4.1",
|
|
48
|
+
"copy-webpack-plugin": "13.0.0",
|
|
49
|
+
"css-loader": "7.1.2",
|
|
50
|
+
"css-minimizer-webpack-plugin": "7.0.2",
|
|
51
|
+
"dotenv-webpack": "8.1.0",
|
|
52
|
+
"eslint": "9.31.0",
|
|
53
|
+
"eslint-plugin-react": "^7.37.5",
|
|
54
|
+
"eslint-webpack-plugin": "5.0.2",
|
|
55
|
+
"file-loader": "6.2.0",
|
|
56
|
+
"glob": "11.0.3",
|
|
57
|
+
"globals": "16.2.0",
|
|
58
|
+
"html-loader": "5.1.0",
|
|
59
|
+
"html-webpack-plugin": "5.6.3",
|
|
60
|
+
"image-webpack-loader": "8.1.0",
|
|
61
|
+
"lodash": "4.17.21",
|
|
62
|
+
"mini-css-extract-plugin": "2.9.2",
|
|
63
|
+
"rollup": "4.44.0",
|
|
64
|
+
"sass": "1.89.2",
|
|
65
|
+
"sass-loader": "16.0.5",
|
|
66
|
+
"style-loader": "4.0.0",
|
|
67
|
+
"terminal-log": "1.0.1",
|
|
68
|
+
"terser-webpack-plugin": "5.3.14",
|
|
69
|
+
"thread-loader": "4.0.4",
|
|
70
|
+
"url-loader": "4.1.1",
|
|
71
|
+
"webpack": "5.99.9",
|
|
72
|
+
"webpack-cli": "6.0.1",
|
|
73
|
+
"webpack-dev-server": "5.2.2",
|
|
74
|
+
"yargs": "18.0.0"
|
|
27
75
|
}
|
|
28
|
-
}
|
|
76
|
+
}
|
package/rspack/index.js
CHANGED
|
@@ -1,92 +1,92 @@
|
|
|
1
|
-
import rspack from '@rspack/core'
|
|
2
|
-
import { resolve, join } from 'path'
|
|
3
|
-
|
|
4
|
-
const resolveApp = (appDirectory, relativePath) =>
|
|
5
|
-
resolve(appDirectory, relativePath)
|
|
6
|
-
|
|
7
|
-
const ryunixRspack = () => {
|
|
8
|
-
const isDev = process.env.NODE_ENV === 'development'
|
|
9
|
-
const dir = process.cwd()
|
|
10
|
-
return {
|
|
11
|
-
mode: isDev ? 'development' : 'production',
|
|
12
|
-
context: resolveApp(dir, 'src'),
|
|
13
|
-
entry: {
|
|
14
|
-
main: './main.ryx',
|
|
15
|
-
},
|
|
16
|
-
devtool: isDev ? 'source-map' : false,
|
|
17
|
-
output: {
|
|
18
|
-
publicPath: '/',
|
|
19
|
-
},
|
|
20
|
-
devServer: {
|
|
21
|
-
hot: isDev,
|
|
22
|
-
historyApiFallback: {
|
|
23
|
-
index: '/',
|
|
24
|
-
disableDotRule: true,
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
module: {
|
|
28
|
-
rules: [
|
|
29
|
-
{
|
|
30
|
-
test: /\.svg$/,
|
|
31
|
-
type: 'asset',
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
test: /\.css$/i,
|
|
35
|
-
use: [rspack.CssExtractRspackPlugin.loader, 'css-loader'],
|
|
36
|
-
type: 'javascript/auto',
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
test: /\.module\.css$/i,
|
|
40
|
-
type: 'css/module',
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
test: /\.(png|jpe?g|gif)$/i,
|
|
44
|
-
type: 'asset/resource',
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
test: /^BUILD_ID$/,
|
|
48
|
-
type: 'asset/source',
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
test: /\.jsx|.ryx$/,
|
|
52
|
-
exclude: [/[\\/]node_modules[\\/]/],
|
|
53
|
-
use: [
|
|
54
|
-
{
|
|
55
|
-
loader: 'builtin:swc-loader',
|
|
56
|
-
options: {
|
|
57
|
-
jsc: {
|
|
58
|
-
parser: {
|
|
59
|
-
syntax: 'ecmascript',
|
|
60
|
-
jsx: true,
|
|
61
|
-
},
|
|
62
|
-
transform: {
|
|
63
|
-
react: {
|
|
64
|
-
pragma: 'Ryunix.createElement',
|
|
65
|
-
pragmaFrag: 'Ryunix.Fragment',
|
|
66
|
-
},
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
},
|
|
71
|
-
],
|
|
72
|
-
type: 'javascript/auto',
|
|
73
|
-
},
|
|
74
|
-
],
|
|
75
|
-
},
|
|
76
|
-
resolve: {
|
|
77
|
-
extensions: ['.*', '.js', '.jsx', '.ryx'],
|
|
78
|
-
},
|
|
79
|
-
plugins: [
|
|
80
|
-
new rspack.CssExtractRspackPlugin({}),
|
|
81
|
-
new rspack.DefinePlugin({
|
|
82
|
-
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
|
|
83
|
-
}),
|
|
84
|
-
new rspack.ProgressPlugin({}),
|
|
85
|
-
new rspack.HtmlRspackPlugin({
|
|
86
|
-
template: join(dir, 'index.html'),
|
|
87
|
-
}),
|
|
88
|
-
].filter(Boolean),
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export { ryunixRspack }
|
|
1
|
+
import rspack from '@rspack/core'
|
|
2
|
+
import { resolve, join } from 'path'
|
|
3
|
+
|
|
4
|
+
const resolveApp = (appDirectory, relativePath) =>
|
|
5
|
+
resolve(appDirectory, relativePath)
|
|
6
|
+
|
|
7
|
+
const ryunixRspack = () => {
|
|
8
|
+
const isDev = process.env.NODE_ENV === 'development'
|
|
9
|
+
const dir = process.cwd()
|
|
10
|
+
return {
|
|
11
|
+
mode: isDev ? 'development' : 'production',
|
|
12
|
+
context: resolveApp(dir, 'src'),
|
|
13
|
+
entry: {
|
|
14
|
+
main: './main.ryx',
|
|
15
|
+
},
|
|
16
|
+
devtool: isDev ? 'source-map' : false,
|
|
17
|
+
output: {
|
|
18
|
+
publicPath: '/',
|
|
19
|
+
},
|
|
20
|
+
devServer: {
|
|
21
|
+
hot: isDev,
|
|
22
|
+
historyApiFallback: {
|
|
23
|
+
index: '/',
|
|
24
|
+
disableDotRule: true,
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
module: {
|
|
28
|
+
rules: [
|
|
29
|
+
{
|
|
30
|
+
test: /\.svg$/,
|
|
31
|
+
type: 'asset',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
test: /\.css$/i,
|
|
35
|
+
use: [rspack.CssExtractRspackPlugin.loader, 'css-loader'],
|
|
36
|
+
type: 'javascript/auto',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
test: /\.module\.css$/i,
|
|
40
|
+
type: 'css/module',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
test: /\.(png|jpe?g|gif)$/i,
|
|
44
|
+
type: 'asset/resource',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
test: /^BUILD_ID$/,
|
|
48
|
+
type: 'asset/source',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
test: /\.jsx|.ryx$/,
|
|
52
|
+
exclude: [/[\\/]node_modules[\\/]/],
|
|
53
|
+
use: [
|
|
54
|
+
{
|
|
55
|
+
loader: 'builtin:swc-loader',
|
|
56
|
+
options: {
|
|
57
|
+
jsc: {
|
|
58
|
+
parser: {
|
|
59
|
+
syntax: 'ecmascript',
|
|
60
|
+
jsx: true,
|
|
61
|
+
},
|
|
62
|
+
transform: {
|
|
63
|
+
react: {
|
|
64
|
+
pragma: 'Ryunix.createElement',
|
|
65
|
+
pragmaFrag: 'Ryunix.Fragment',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
type: 'javascript/auto',
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
resolve: {
|
|
77
|
+
extensions: ['.*', '.js', '.jsx', '.ryx'],
|
|
78
|
+
},
|
|
79
|
+
plugins: [
|
|
80
|
+
new rspack.CssExtractRspackPlugin({}),
|
|
81
|
+
new rspack.DefinePlugin({
|
|
82
|
+
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
|
|
83
|
+
}),
|
|
84
|
+
new rspack.ProgressPlugin({}),
|
|
85
|
+
new rspack.HtmlRspackPlugin({
|
|
86
|
+
template: join(dir, 'index.html'),
|
|
87
|
+
}),
|
|
88
|
+
].filter(Boolean),
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export { ryunixRspack }
|
package/vite/index.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
const ryunixPlugin = () => {
|
|
2
|
-
const jsxPlugin = {
|
|
3
|
-
name: 'vite:ryunix-jsx',
|
|
4
|
-
config() {
|
|
5
|
-
return {
|
|
6
|
-
esbuild: {
|
|
7
|
-
jsxFactory: 'Ryunix.createElement',
|
|
8
|
-
jsxFragment: 'Ryunix.Fragment',
|
|
9
|
-
},
|
|
10
|
-
}
|
|
11
|
-
},
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
return [jsxPlugin]
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export default ryunixPlugin
|
|
18
|
-
export { ryunixPlugin as ryunixVite }
|
|
1
|
+
const ryunixPlugin = () => {
|
|
2
|
+
const jsxPlugin = {
|
|
3
|
+
name: 'vite:ryunix-jsx',
|
|
4
|
+
config() {
|
|
5
|
+
return {
|
|
6
|
+
esbuild: {
|
|
7
|
+
jsxFactory: 'Ryunix.createElement',
|
|
8
|
+
jsxFragment: 'Ryunix.Fragment',
|
|
9
|
+
},
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return [jsxPlugin]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default ryunixPlugin
|
|
18
|
+
export { ryunixPlugin as ryunixVite }
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#! /usr/bin/env node
|
|
2
|
+
import yargs from 'yargs'
|
|
3
|
+
import { hideBin } from 'yargs/helpers'
|
|
4
|
+
import { StartServer } from './serve.mjs'
|
|
5
|
+
import { compiler } from './compiler.mjs'
|
|
6
|
+
import logger from 'terminal-log'
|
|
7
|
+
import chalk from 'chalk'
|
|
8
|
+
import defaultSettings from '../utils/config.cjs'
|
|
9
|
+
import Prerender from './prerender.mjs'
|
|
10
|
+
import {
|
|
11
|
+
cleanBuildDirectory,
|
|
12
|
+
convertFlatToClassic,
|
|
13
|
+
resolveApp,
|
|
14
|
+
} from '../utils/index.mjs'
|
|
15
|
+
import { ESLint } from 'eslint'
|
|
16
|
+
import eslintConfig from '../eslint.config.mjs'
|
|
17
|
+
const lint = {
|
|
18
|
+
command: 'lint',
|
|
19
|
+
describe: 'Lint code',
|
|
20
|
+
builder: {
|
|
21
|
+
fix: {
|
|
22
|
+
alias: 'f',
|
|
23
|
+
type: 'boolean',
|
|
24
|
+
default: false,
|
|
25
|
+
describe: 'Automatically fix problems',
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
handler: async (arg) => {
|
|
29
|
+
const classicConfig = eslintConfig[0]
|
|
30
|
+
|
|
31
|
+
const fix = arg.fix
|
|
32
|
+
const eslint = new ESLint({
|
|
33
|
+
cwd: process.cwd(),
|
|
34
|
+
overrideConfigFile: true,
|
|
35
|
+
overrideConfig: classicConfig,
|
|
36
|
+
fix,
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
const results = await eslint.lintFiles(defaultSettings.eslint.files)
|
|
40
|
+
|
|
41
|
+
await ESLint.outputFixes(results)
|
|
42
|
+
|
|
43
|
+
const formatter = await eslint.loadFormatter('stylish')
|
|
44
|
+
const report = formatter.format(results)
|
|
45
|
+
console.log(report)
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const serv = {
|
|
50
|
+
command: 'server',
|
|
51
|
+
describe: 'Run server',
|
|
52
|
+
handler: async (arg) => {
|
|
53
|
+
const open = Boolean(arg.browser) || false
|
|
54
|
+
const settings = {
|
|
55
|
+
open,
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
StartServer(settings)
|
|
59
|
+
},
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const build = {
|
|
63
|
+
command: 'build',
|
|
64
|
+
describe: 'Run builder',
|
|
65
|
+
handler: async (arg) => {
|
|
66
|
+
if (!defaultSettings.webpack.production) {
|
|
67
|
+
logger.error(
|
|
68
|
+
chalk.red(
|
|
69
|
+
'The compilation cannot complete because you are trying to compile in developer mode. remember update ryunix.config.js.',
|
|
70
|
+
),
|
|
71
|
+
)
|
|
72
|
+
return
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (defaultSettings.experimental.ssg.prerender.length > 0) {
|
|
76
|
+
await cleanBuildDirectory(
|
|
77
|
+
resolveApp(
|
|
78
|
+
process.cwd(),
|
|
79
|
+
`${defaultSettings.webpack.output.buildDirectory}/static`,
|
|
80
|
+
),
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
compiler.run(async (err, stats) => {
|
|
85
|
+
if (err || stats.hasErrors()) {
|
|
86
|
+
logger.error(chalk.red('Error during compilation:'))
|
|
87
|
+
logger.error(err || stats.toString('errors-only'))
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const buildTimeMs = stats.endTime - stats.startTime
|
|
92
|
+
|
|
93
|
+
const minutes = Math.floor(buildTimeMs / 60000)
|
|
94
|
+
const seconds = ((buildTimeMs % 60000) / 1000).toFixed(1)
|
|
95
|
+
|
|
96
|
+
const formattedTime =
|
|
97
|
+
minutes > 0 ? `${minutes}m ${seconds}s` : `${seconds}s`
|
|
98
|
+
|
|
99
|
+
if (defaultSettings.experimental.ssg.prerender.length > 0) {
|
|
100
|
+
await Prerender()
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
logger.info(chalk.green('Compilation successful! 🎉'))
|
|
104
|
+
logger.info(`Done in ${formattedTime}`)
|
|
105
|
+
|
|
106
|
+
compiler.close((closeErr) => {
|
|
107
|
+
if (closeErr) {
|
|
108
|
+
logger.error(chalk.red('Error closing the compiler:'), closeErr)
|
|
109
|
+
}
|
|
110
|
+
})
|
|
111
|
+
})
|
|
112
|
+
},
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
yargs(hideBin(process.argv)).command(serv).command(build).command(lint).parse()
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* prerender metadata
|
|
3
|
+
*
|
|
4
|
+
*/
|
|
5
|
+
import { configFileExist } from '../utils/settingfile.cjs'
|
|
6
|
+
import defaultSettings from '../utils/config.cjs'
|
|
7
|
+
import { resolveApp } from '../utils/index.mjs'
|
|
8
|
+
import fs from 'fs'
|
|
9
|
+
import path from 'path'
|
|
10
|
+
|
|
11
|
+
// proyect/.ryunix/static
|
|
12
|
+
const buildDirectory = resolveApp(process.cwd(), '.ryunix/static')
|
|
13
|
+
const indexFile = path.join(buildDirectory, 'index.html')
|
|
14
|
+
|
|
15
|
+
const siteMap = async (routes) => {
|
|
16
|
+
if (!defaultSettings.experimental.ssg.sitemap.baseURL) {
|
|
17
|
+
console.error(
|
|
18
|
+
'❌ Base URL is not defined in the configuration file. Please set `experimental.ssg.sitemap.baseURL`.',
|
|
19
|
+
)
|
|
20
|
+
process.exit(1)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
|
|
24
|
+
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
25
|
+
${routes
|
|
26
|
+
.map((route) => {
|
|
27
|
+
const url = `${defaultSettings.experimental.ssg.sitemap.baseURL}${route.path === '/' ? '' : route.path}`
|
|
28
|
+
const meta = route.meta || {}
|
|
29
|
+
const sitemap_settings = route.sitemap || {}
|
|
30
|
+
const lastmod = meta.lastmod || new Date().toISOString().split('T')[0]
|
|
31
|
+
|
|
32
|
+
// sitemap settings
|
|
33
|
+
const changefreq =
|
|
34
|
+
sitemap_settings.changefreq ||
|
|
35
|
+
meta.changefreq || // TODO: Remove meta.changefreq
|
|
36
|
+
defaultSettings.experimental.ssg.sitemap.settings.changefreq
|
|
37
|
+
const priority =
|
|
38
|
+
sitemap_settings.priority ||
|
|
39
|
+
meta.priority || // TODO: Remove meta.priority
|
|
40
|
+
defaultSettings.experimental.ssg.sitemap.settings.priority
|
|
41
|
+
|
|
42
|
+
return `<url>
|
|
43
|
+
<loc>${url}</loc>
|
|
44
|
+
<lastmod>${lastmod}</lastmod>
|
|
45
|
+
<changefreq>${changefreq}</changefreq>
|
|
46
|
+
<priority>${priority}</priority>
|
|
47
|
+
</url>`
|
|
48
|
+
})
|
|
49
|
+
.join('\n')}
|
|
50
|
+
</urlset>`
|
|
51
|
+
|
|
52
|
+
await fs.writeFileSync(
|
|
53
|
+
path.resolve(buildDirectory, 'sitemap.xml'),
|
|
54
|
+
sitemap,
|
|
55
|
+
'utf-8',
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
console.log('✅ Sitemap created')
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const Prerender = async () => {
|
|
62
|
+
if (!configFileExist()) {
|
|
63
|
+
console.error('❌ No configuration file found.')
|
|
64
|
+
process.exit(1)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const template = fs.readFileSync(indexFile, 'utf-8')
|
|
68
|
+
|
|
69
|
+
for (const route of defaultSettings.experimental.ssg.prerender) {
|
|
70
|
+
if (route.path === '/') continue // Exclude root path, handled by defaultSettings.static.seo.meta
|
|
71
|
+
let html = template
|
|
72
|
+
const meta = route?.meta || defaultSettings.static.seo.meta
|
|
73
|
+
|
|
74
|
+
// title
|
|
75
|
+
if (meta.title) {
|
|
76
|
+
html = html.replace(/<title>.*<\/title>/, `<title>${meta.title}<\/title>`)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Helper to add or replace metatag
|
|
80
|
+
function upsertMetaTag(html, name, value) {
|
|
81
|
+
if (value === undefined || value === null) return html
|
|
82
|
+
|
|
83
|
+
const isProperty = name.startsWith('og:') || name.startsWith('twitter:')
|
|
84
|
+
const attr = isProperty ? 'property' : 'name'
|
|
85
|
+
const regex = new RegExp(`<meta ${attr}=["']${name}["'][^>]*>`, 'i')
|
|
86
|
+
const tag = `<meta ${attr}="${name}" content="${value}">`
|
|
87
|
+
|
|
88
|
+
if (regex.test(html)) {
|
|
89
|
+
return html.replace(regex, tag)
|
|
90
|
+
} else {
|
|
91
|
+
return html.replace(/<\/head>/i, `${tag}\n<\/head>`)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Description
|
|
96
|
+
html = upsertMetaTag(html, 'description', meta.description)
|
|
97
|
+
// Keywords
|
|
98
|
+
html = upsertMetaTag(html, 'keywords', meta.keywords)
|
|
99
|
+
|
|
100
|
+
// dynamic metatags (excluding title, description, keywords, framework, mode)
|
|
101
|
+
for (const [key, value] of Object.entries(meta)) {
|
|
102
|
+
if (
|
|
103
|
+
[
|
|
104
|
+
'title',
|
|
105
|
+
'description',
|
|
106
|
+
'keywords',
|
|
107
|
+
'framework',
|
|
108
|
+
'mode',
|
|
109
|
+
'viewport',
|
|
110
|
+
].includes(key)
|
|
111
|
+
)
|
|
112
|
+
continue
|
|
113
|
+
html = upsertMetaTag(html, key, value)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const outputDir =
|
|
117
|
+
route.path === '/'
|
|
118
|
+
? buildDirectory
|
|
119
|
+
: path.join(buildDirectory, route.path)
|
|
120
|
+
|
|
121
|
+
if (!fs.existsSync(outputDir)) {
|
|
122
|
+
await fs.mkdirSync(outputDir, { recursive: true, force: true })
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
await fs.writeFileSync(path.join(outputDir, 'index.html'), html)
|
|
126
|
+
console.log(`✅ Prerendered ${route.path}`)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// need base url and enable
|
|
130
|
+
if (
|
|
131
|
+
defaultSettings.experimental.ssg.sitemap.enable &&
|
|
132
|
+
defaultSettings.experimental.ssg.sitemap.baseURL
|
|
133
|
+
) {
|
|
134
|
+
await siteMap(defaultSettings.experimental.ssg.prerender)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export default Prerender
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import Webpack from 'webpack'
|
|
2
|
+
import WebpackDevServer from 'webpack-dev-server'
|
|
3
|
+
import webpackConfig from '../webpack.config.mjs'
|
|
4
|
+
import { configFileExist } from '../utils/settingfile.cjs'
|
|
5
|
+
import envPath from '../utils/envExist.cjs'
|
|
6
|
+
import {
|
|
7
|
+
getPackageVersion,
|
|
8
|
+
resolveApp,
|
|
9
|
+
cleanCacheDir,
|
|
10
|
+
} from '../utils/index.mjs'
|
|
11
|
+
import logger from 'terminal-log'
|
|
12
|
+
import chalk from 'chalk'
|
|
13
|
+
import net from 'net' // Para verificar si el puerto está disponible
|
|
14
|
+
import defaultSettings from '../utils/config.cjs'
|
|
15
|
+
|
|
16
|
+
const checkPortInUse = (port) => {
|
|
17
|
+
return new Promise((resolve, reject) => {
|
|
18
|
+
const server = net.createServer()
|
|
19
|
+
server.once('error', (err) => {
|
|
20
|
+
if (err.code === 'EADDRINUSE') {
|
|
21
|
+
resolve(true) // Puerto en uso
|
|
22
|
+
} else {
|
|
23
|
+
reject(err)
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
server.once('listening', () => {
|
|
27
|
+
server.close()
|
|
28
|
+
resolve(false) // Puerto libre
|
|
29
|
+
})
|
|
30
|
+
server.listen(port)
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const findAvailablePort = async (port) => {
|
|
35
|
+
let isPortInUse = await checkPortInUse(port)
|
|
36
|
+
while (isPortInUse) {
|
|
37
|
+
logger.warn(
|
|
38
|
+
chalk.yellow(`Port ${port} is in use, trying port ${port + 1}...`),
|
|
39
|
+
)
|
|
40
|
+
port += 1
|
|
41
|
+
isPortInUse = await checkPortInUse(port)
|
|
42
|
+
}
|
|
43
|
+
return port
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const StartServer = async (cliSettings) => {
|
|
47
|
+
const cacheDir = resolveApp(
|
|
48
|
+
process.cwd(),
|
|
49
|
+
`${defaultSettings.webpack.output.buildDirectory}/cache`,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
if (!defaultSettings.webpack.production) {
|
|
53
|
+
cleanCacheDir(cacheDir)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
webpackConfig.mode = 'development'
|
|
57
|
+
const compiler = Webpack(webpackConfig)
|
|
58
|
+
let port = webpackConfig.devServer.port || 3000
|
|
59
|
+
|
|
60
|
+
// Encontrar un puerto disponible
|
|
61
|
+
port = await findAvailablePort(port)
|
|
62
|
+
|
|
63
|
+
// Modificamos el puerto en la configuración
|
|
64
|
+
webpackConfig.devServer.port = port
|
|
65
|
+
const devServerOptions = { ...webpackConfig.devServer, ...cliSettings }
|
|
66
|
+
const server = new WebpackDevServer(devServerOptions, compiler)
|
|
67
|
+
|
|
68
|
+
const devMode = Boolean(!defaultSettings.webpack.production)
|
|
69
|
+
|
|
70
|
+
const { version } = await getPackageVersion()
|
|
71
|
+
|
|
72
|
+
const startServer = async () => {
|
|
73
|
+
try {
|
|
74
|
+
await server.start() // Iniciar el servidor con el nuevo puerto
|
|
75
|
+
|
|
76
|
+
// Mejor formato de información para el servidor
|
|
77
|
+
const url = `http://localhost:${port}`
|
|
78
|
+
const cfgStatus = configFileExist() ? chalk.green('loaded') : chalk.red('not found')
|
|
79
|
+
const envStatus = envPath() ? chalk.green('loaded') : chalk.yellow('not found')
|
|
80
|
+
const modeLabel = defaultSettings.webpack.production ? chalk.green('production') : chalk.yellow('development')
|
|
81
|
+
|
|
82
|
+
const lines = []
|
|
83
|
+
lines.push(chalk.bold(chalk.cyanBright(`<Ryunix/> ${version}`)))
|
|
84
|
+
lines.push('')
|
|
85
|
+
lines.push(`${chalk.gray('-')} Running at: ${chalk.underline(url)}`)
|
|
86
|
+
lines.push(`${chalk.gray('-')} Config file: ${cfgStatus}`)
|
|
87
|
+
lines.push(`${chalk.gray('-')} Environment file: ${envStatus}`)
|
|
88
|
+
lines.push(`${chalk.gray('-')} Mode: ${modeLabel}`)
|
|
89
|
+
if (devMode) lines.push(chalk.yellow('⚠️ You are in development mode — update ryunix.config.js for production'))
|
|
90
|
+
|
|
91
|
+
lines.push('---------------------------')
|
|
92
|
+
logger.info(lines.join('\n'))
|
|
93
|
+
} catch (err) {
|
|
94
|
+
logger.error(`[error] ${err.message}`)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
await startServer()
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export { StartServer }
|