@modern-js/module-tools-docs 2.59.0 → 2.60.1
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/CHANGELOG.md +4 -0
- package/doc_build/404.html +17 -0
- package/doc_build/api/config/build-config.html +1217 -0
- package/doc_build/api/config/build-preset.html +211 -0
- package/doc_build/api/config/dev.html +63 -0
- package/doc_build/api/config/plugins.html +54 -0
- package/doc_build/api/index.html +17 -0
- package/doc_build/api/plugin-api/plugin-hooks.html +395 -0
- package/doc_build/components/faq-build-exception.html +17 -0
- package/doc_build/components/faq-build-other.html +17 -0
- package/doc_build/components/faq-build-product.html +17 -0
- package/doc_build/components/faq-storybook.html +17 -0
- package/doc_build/components/publish-emo.html +17 -0
- package/doc_build/components/register-esbuild-plugin.html +27 -0
- package/doc_build/components/release-module-doc.html +17 -0
- package/doc_build/en/api/config/build-config.html +1220 -0
- package/doc_build/en/api/config/build-preset.html +206 -0
- package/doc_build/en/api/config/dev.html +63 -0
- package/doc_build/en/api/config/plugins.html +54 -0
- package/doc_build/en/api/index.html +17 -0
- package/doc_build/en/api/plugin-api/plugin-hooks.html +399 -0
- package/doc_build/en/components/faq-build-exception.html +17 -0
- package/doc_build/en/components/faq-build-other.html +17 -0
- package/doc_build/en/components/faq-build-product.html +17 -0
- package/doc_build/en/components/faq-storybook.html +17 -0
- package/doc_build/en/components/publish-emo.html +17 -0
- package/doc_build/en/components/register-esbuild-plugin.html +27 -0
- package/doc_build/en/components/release-module-doc.html +17 -0
- package/doc_build/en/guide/advance/asset.html +58 -0
- package/doc_build/en/guide/advance/build-umd.html +166 -0
- package/doc_build/en/guide/advance/copy.html +208 -0
- package/doc_build/en/guide/advance/external-dependency.html +62 -0
- package/doc_build/en/guide/advance/in-depth-about-build.html +302 -0
- package/doc_build/en/guide/advance/in-depth-about-dev-command.html +68 -0
- package/doc_build/en/guide/basic/before-getting-started.html +139 -0
- package/doc_build/en/guide/basic/command-preview.html +131 -0
- package/doc_build/en/guide/basic/modify-output-product.html +133 -0
- package/doc_build/en/guide/basic/publish-your-project.html +100 -0
- package/doc_build/en/guide/basic/use-micro-generator.html +54 -0
- package/doc_build/en/guide/basic/use-module-doc.html +397 -0
- package/doc_build/en/guide/basic/using-storybook.html +168 -0
- package/doc_build/en/guide/best-practices/components.html +198 -0
- package/doc_build/en/guide/best-practices/use-tailwindcss.html +243 -0
- package/doc_build/en/guide/faq/basic.html +23 -0
- package/doc_build/en/guide/faq/build.html +237 -0
- package/doc_build/en/guide/faq/index.html +23 -0
- package/doc_build/en/guide/faq/storybook.html +85 -0
- package/doc_build/en/guide/intro/getting-started.html +92 -0
- package/doc_build/en/guide/intro/welcome.html +27 -0
- package/doc_build/en/guide/intro/why-module-engineering-solution.html +25 -0
- package/doc_build/en/index.html +17 -0
- package/doc_build/en/plugins/guide/getting-started.html +70 -0
- package/doc_build/en/plugins/guide/plugin-object.html +74 -0
- package/doc_build/en/plugins/guide/setup-function.html +96 -0
- package/doc_build/en/plugins/official-list/overview.html +26 -0
- package/doc_build/en/plugins/official-list/plugin-babel.html +65 -0
- package/doc_build/en/plugins/official-list/plugin-banner.html +91 -0
- package/doc_build/en/plugins/official-list/plugin-import.html +111 -0
- package/doc_build/en/plugins/official-list/plugin-node-polyfill.html +128 -0
- package/doc_build/en/plugins/official-list/plugin-polyfill.html +72 -0
- package/doc_build/en/plugins/official-list/plugin-vue.html +66 -0
- package/doc_build/guide/advance/asset.html +55 -0
- package/doc_build/guide/advance/build-umd.html +170 -0
- package/doc_build/guide/advance/copy.html +208 -0
- package/doc_build/guide/advance/external-dependency.html +61 -0
- package/doc_build/guide/advance/in-depth-about-build.html +300 -0
- package/doc_build/guide/advance/in-depth-about-dev-command.html +68 -0
- package/doc_build/guide/basic/before-getting-started.html +139 -0
- package/doc_build/guide/basic/command-preview.html +131 -0
- package/doc_build/guide/basic/modify-output-product.html +134 -0
- package/doc_build/guide/basic/publish-your-project.html +99 -0
- package/doc_build/guide/basic/use-micro-generator.html +54 -0
- package/doc_build/guide/basic/use-module-doc.html +395 -0
- package/doc_build/guide/basic/using-storybook.html +177 -0
- package/doc_build/guide/best-practices/components.html +198 -0
- package/doc_build/guide/best-practices/use-tailwindcss.html +243 -0
- package/doc_build/guide/faq/basic.html +23 -0
- package/doc_build/guide/faq/build.html +234 -0
- package/doc_build/guide/faq/index.html +23 -0
- package/doc_build/guide/faq/storybook.html +85 -0
- package/doc_build/guide/intro/getting-started.html +89 -0
- package/doc_build/guide/intro/welcome.html +27 -0
- package/doc_build/guide/intro/why-module-engineering-solution.html +25 -0
- package/doc_build/index.html +17 -0
- package/doc_build/plugins/guide/getting-started.html +70 -0
- package/doc_build/plugins/guide/plugin-object.html +74 -0
- package/doc_build/plugins/guide/setup-function.html +95 -0
- package/doc_build/plugins/official-list/overview.html +26 -0
- package/doc_build/plugins/official-list/plugin-babel.html +64 -0
- package/doc_build/plugins/official-list/plugin-banner.html +94 -0
- package/doc_build/plugins/official-list/plugin-import.html +112 -0
- package/doc_build/plugins/official-list/plugin-node-polyfill.html +128 -0
- package/doc_build/plugins/official-list/plugin-polyfill.html +71 -0
- package/doc_build/plugins/official-list/plugin-vue.html +66 -0
- package/doc_build/static/css/styles.0b88df3a.css +1 -0
- package/doc_build/static/js/490.a066dbc0.js +6 -0
- package/doc_build/static/js/490.a066dbc0.js.LICENSE.txt +35 -0
- package/doc_build/static/js/async/1095.4ca5fdf0.js +1 -0
- package/doc_build/static/js/async/1148.ff6a84ca.js +1 -0
- package/doc_build/static/js/async/1306.8bc84d6b.js +1 -0
- package/doc_build/static/js/async/1507.fed31a58.js +1 -0
- package/doc_build/static/js/async/1527.4c6e53e2.js +1 -0
- package/doc_build/static/js/async/1657.d0d95d59.js +1 -0
- package/doc_build/static/js/async/1801.5d49a2fe.js +1 -0
- package/doc_build/static/js/async/1941.0b3cceee.js +1 -0
- package/doc_build/static/js/async/213.db8a0492.js +1 -0
- package/doc_build/static/js/async/2131.5dfdffa9.js +1 -0
- package/doc_build/static/js/async/2140.848412d7.js +1 -0
- package/doc_build/static/js/async/2206.f6b802b2.js +1 -0
- package/doc_build/static/js/async/2300.cba0106e.js +1 -0
- package/doc_build/static/js/async/2347.a480682f.js +1 -0
- package/doc_build/static/js/async/2365.daed0a9c.js +1 -0
- package/doc_build/static/js/async/2561.2e43400c.js +1 -0
- package/doc_build/static/js/async/2579.f7c71e6b.js +1 -0
- package/doc_build/static/js/async/2671.c711355f.js +1 -0
- package/doc_build/static/js/async/2704.561dadd9.js +1 -0
- package/doc_build/static/js/async/2712.5ffea5ba.js +1 -0
- package/doc_build/static/js/async/3023.5bef6325.js +1 -0
- package/doc_build/static/js/async/3039.3982622e.js +1 -0
- package/doc_build/static/js/async/3097.b043b3aa.js +1 -0
- package/doc_build/static/js/async/3213.df408a99.js +1 -0
- package/doc_build/static/js/async/3235.0c4d2c9b.js +1 -0
- package/doc_build/static/js/async/336.8387125c.js +1 -0
- package/doc_build/static/js/async/3493.5133deaa.js +1 -0
- package/doc_build/static/js/async/351.de7824af.js +1 -0
- package/doc_build/static/js/async/3597.cf46a69b.js +1 -0
- package/doc_build/static/js/async/36.eee0e8fe.js +1 -0
- package/doc_build/static/js/async/3628.726e3f10.js +1 -0
- package/doc_build/static/js/async/3724.bcc90bb4.js +1 -0
- package/doc_build/static/js/async/3761.949f5838.js +1 -0
- package/doc_build/static/js/async/4061.84ac839b.js +1 -0
- package/doc_build/static/js/async/4064.104b71cd.js +1 -0
- package/doc_build/static/js/async/4206.133ffe9e.js +1 -0
- package/doc_build/static/js/async/443.b519ce6b.js +1 -0
- package/doc_build/static/js/async/4501.c647ab73.js +1 -0
- package/doc_build/static/js/async/453.7358c1fd.js +1 -0
- package/doc_build/static/js/async/461.2d6ea16c.js +1 -0
- package/doc_build/static/js/async/4615.c4e5b749.js +1 -0
- package/doc_build/static/js/async/4655.bbe27e7b.js +1 -0
- package/doc_build/static/js/async/4812.ebd3f4cb.js +1 -0
- package/doc_build/static/js/async/4904.de72a299.js +1 -0
- package/doc_build/static/js/async/5105.28347c4d.js +1 -0
- package/doc_build/static/js/async/5453.87dcea50.js +1 -0
- package/doc_build/static/js/async/5455.9e038fda.js +1 -0
- package/doc_build/static/js/async/5493.3644c7b8.js +1 -0
- package/doc_build/static/js/async/5495.50aacc7e.js +1 -0
- package/doc_build/static/js/async/5555.40dabd12.js +1 -0
- package/doc_build/static/js/async/5558.073d18d0.js +1 -0
- package/doc_build/static/js/async/5844.b3a9d57a.js +1 -0
- package/doc_build/static/js/async/588.6de9811a.js +1 -0
- package/doc_build/static/js/async/5889.41a786b6.js +1 -0
- package/doc_build/static/js/async/5892.b0db6657.js +1 -0
- package/doc_build/static/js/async/5995.209e2925.js +1 -0
- package/doc_build/static/js/async/6046.963bbf59.js +1 -0
- package/doc_build/static/js/async/6308.6363792d.js +1 -0
- package/doc_build/static/js/async/6576.a753babb.js +1 -0
- package/doc_build/static/js/async/6615.154a2810.js +1 -0
- package/doc_build/static/js/async/6858.e2452605.js +1 -0
- package/doc_build/static/js/async/6975.be4ba201.js +1 -0
- package/doc_build/static/js/async/7080.1c684c7d.js +1 -0
- package/doc_build/static/js/async/7220.1c4ee8bb.js +1 -0
- package/doc_build/static/js/async/7406.b2acec42.js +1 -0
- package/doc_build/static/js/async/7521.ca744786.js +1 -0
- package/doc_build/static/js/async/7535.f50f0fd1.js +1 -0
- package/doc_build/static/js/async/7584.c3b673fd.js +1 -0
- package/doc_build/static/js/async/7600.03d9da89.js +1 -0
- package/doc_build/static/js/async/7663.86b79735.js +1 -0
- package/doc_build/static/js/async/769.2bc1c7b7.js +1 -0
- package/doc_build/static/js/async/7715.1bfe887f.js +1 -0
- package/doc_build/static/js/async/7837.5667c422.js +1 -0
- package/doc_build/static/js/async/8040.1cfb21ff.js +1 -0
- package/doc_build/static/js/async/8085.f9f71860.js +1 -0
- package/doc_build/static/js/async/8098.beeb77f3.js +1 -0
- package/doc_build/static/js/async/8134.068074a0.js +1 -0
- package/doc_build/static/js/async/8158.2834ced1.js +1 -0
- package/doc_build/static/js/async/8214.2fdfe2fe.js +1 -0
- package/doc_build/static/js/async/8233.24111213.js +1 -0
- package/doc_build/static/js/async/8451.5328c0c7.js +1 -0
- package/doc_build/static/js/async/8689.f8447ca1.js +1 -0
- package/doc_build/static/js/async/8694.077556c4.js +1 -0
- package/doc_build/static/js/async/8713.91395601.js +1 -0
- package/doc_build/static/js/async/8750.0f6872b3.js +1 -0
- package/doc_build/static/js/async/8802.463e3040.js +1 -0
- package/doc_build/static/js/async/9100.066e1017.js +1 -0
- package/doc_build/static/js/async/9250.8fb41a47.js +1 -0
- package/doc_build/static/js/async/9524.bb257861.js +1 -0
- package/doc_build/static/js/async/9611.b2543acb.js +1 -0
- package/doc_build/static/js/async/964.b00f3e9f.js +1 -0
- package/doc_build/static/js/async/9740.b27e6629.js +1 -0
- package/doc_build/static/js/index.6a5d779d.js +1 -0
- package/doc_build/static/js/lib-react.a93218f7.js +2 -0
- package/doc_build/static/js/lib-react.a93218f7.js.LICENSE.txt +39 -0
- package/doc_build/static/js/lib-router.f8d11890.js +2 -0
- package/doc_build/static/js/lib-router.f8d11890.js.LICENSE.txt +32 -0
- package/doc_build/static/js/styles.3f5a6140.js +1 -0
- package/doc_build/static/search_index.en.f19ea64b.json +1 -0
- package/doc_build/static/search_index.zh.e818eee4.json +1 -0
- package/doc_build/test-result.png +0 -0
- package/doc_build/why-module-solution.png +0 -0
- package/docs/en/api/config/dev.md +2 -2
- package/docs/en/guide/basic/command-preview.md +0 -16
- package/docs/en/guide/intro/welcome.md +0 -1
- package/docs/zh/api/config/dev.md +2 -2
- package/docs/zh/guide/basic/command-preview.md +0 -16
- package/docs/zh/guide/basic/using-storybook.mdx +1 -1
- package/docs/zh/guide/intro/welcome.md +0 -1
- package/package.json +4 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_modern_js_module_tools_docs=self.webpackChunk_modern_js_module_tools_docs||[]).push([["7715"],{4967:function(e,i,n){n.r(i),n.d(i,{default:function(){return t}});var r=n(8093),s=n(5878);function o(e){let i=Object.assign({h1:"h1",a:"a",h2:"h2",p:"p",code:"code",pre:"pre",strong:"strong",ul:"ul",li:"li",ol:"ol",em:"em"},(0,s.ah)(),e.components);return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(i.h1,{id:"modify-the-output",children:["Modify the output",(0,r.jsx)(i.a,{className:"header-anchor","aria-hidden":"true",href:"#modify-the-output",children:"#"})]}),"\n",(0,r.jsxs)(i.h2,{id:"default-output-artifacts",children:["Default output artifacts",(0,r.jsx)(i.a,{className:"header-anchor","aria-hidden":"true",href:"#default-output-artifacts",children:"#"})]}),"\n",(0,r.jsxs)(i.p,{children:["When you use the ",(0,r.jsx)(i.code,{children:"modern build"})," command in an initialized project, Modern.js Module will generate corresponding build artifacts based on the current configuration."]}),"\n",(0,r.jsx)(i.p,{children:"The default configuration is as follows:"}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{className:"language-ts",meta:'title="modern.config.ts"',children:"import { moduleTools, defineConfig } from '@modern-js/module-tools';\n\nexport default defineConfig({\n // Register the CLI tool of Modern.js Module\n plugins: [moduleTools()],\n // Specify the build preset configuration\n buildPreset: 'npm-library',\n});\n"})}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.strong,{children:"The default output files has the following characteristics"}),"."]}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsxs)(i.li,{children:["will generate ",(0,r.jsx)(i.a,{href:"https://nodejs.org/api/modules.html#modules-commonjs-modules",target:"_blank",rel:"noopener noreferrer",children:"CommonJS"})," and ",(0,r.jsx)(i.a,{href:"https://nodejs.org/api/esm.html#modules-ecmascript-modules",target:"_blank",rel:"noopener noreferrer",children:"ESM"}),"."]}),"\n",(0,r.jsxs)(i.li,{children:["The code syntax is supported up to ",(0,r.jsx)(i.code,{children:"ES6"})," , and more advanced syntax will be converted."]}),"\n",(0,r.jsxs)(i.li,{children:["All code is bundled into one file, i.e. ",(0,r.jsx)(i.strong,{children:"bundle"})," processing is performed."]}),"\n",(0,r.jsxs)(i.li,{children:["The output root directory is the ",(0,r.jsx)(i.code,{children:"dist"})," directory under the project, and the type file output directory is ",(0,r.jsx)(i.code,{children:"dist/types"}),"."]}),"\n"]}),"\n",(0,r.jsx)(i.p,{children:"You may have the following questions when you see this."}),"\n",(0,r.jsxs)(i.ol,{children:["\n",(0,r.jsxs)(i.li,{children:["what is ",(0,r.jsx)(i.code,{children:"buildPreset"}),"?"]}),"\n",(0,r.jsx)(i.li,{children:"what determines these characteristics of the product?"}),"\n"]}),"\n",(0,r.jsxs)(i.p,{children:["Then the next step is to first explain ",(0,r.jsx)(i.code,{children:"buildPreset"}),"."]}),"\n",(0,r.jsxs)(i.h2,{id:"buildpreset",children:["buildPreset",(0,r.jsx)(i.a,{className:"header-anchor","aria-hidden":"true",href:"#buildpreset",children:"#"})]}),"\n",(0,r.jsxs)(i.p,{children:["The ",(0,r.jsx)(i.code,{children:"buildPreset"})," represents a prepared set or sets of build-related configurations that can be used to eliminate the trouble and complexity of configuration by using the default values corresponding to the build Preset, resulting in the expected product."]}),"\n",(0,r.jsx)(i.p,{children:"Modern.js Module mainly comes with two built-in build presets, including:"}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsx)(i.li,{children:"npm-component: Used to build component libraries."}),"\n",(0,r.jsx)(i.li,{children:"npm-library: Used to package projects of other library types, such as tool libraries."}),"\n"]}),"\n",(0,r.jsxs)(i.p,{children:["It also provides some variations, such as ",(0,r.jsx)(i.code,{children:"npm-library-with-umd"})," and ",(0,r.jsx)(i.code,{children:"npm-library-es5"}),", which, as their names suggest, correspond to library presets with umd output and support for es5 syntax, respectively. For more detailed configuration, you can refer to its ",(0,r.jsx)(i.a,{href:"/api/config/build-preset",children:"API"}),"."]}),"\n",(0,r.jsx)(i.p,{children:"In addition, we can also fully customize the build configuration:"}),"\n",(0,r.jsxs)(i.h2,{id:"buildconfig",children:["buildConfig",(0,r.jsx)(i.a,{className:"header-anchor","aria-hidden":"true",href:"#buildconfig",children:"#"})]}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsxs)(i.strong,{children:[(0,r.jsx)(i.code,{children:"buildConfig"})," is a configuration option that describes how to compile and generate build artifacts"]}),'. What was mentioned at the beginning about "',(0,r.jsx)(i.em,{children:"features of build artifacts"}),'" are actually properties supported by ',(0,r.jsx)(i.code,{children:"buildConfig"}),". The currently supported properties cover the needs of most module type projects when building artifacts. ",(0,r.jsx)(i.code,{children:"buildConfig"})," not only contains some properties that artifacts have, but also contains some features needed to build artifacts. The following is a brief list from a classification point of view."]}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.strong,{children:"The basic attributes of a build artifacts include:"})}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsxs)(i.li,{children:["Whether the artifact is bundled or not: the corresponding API is ",(0,r.jsx)(i.a,{href:"/api/config/build-config#buildtype",children:(0,r.jsx)(i.code,{children:"buildConfig.buildType"})}),"."]}),"\n",(0,r.jsxs)(i.li,{children:["Product support for syntax: the corresponding API is ",(0,r.jsx)(i.a,{href:"/api/config/build-config#target",children:(0,r.jsx)(i.code,{children:"buildConfig.target"})}),"."]}),"\n",(0,r.jsxs)(i.li,{children:["Output format: the corresponding API is ",(0,r.jsx)(i.a,{href:"/api/config/build-config#format",children:(0,r.jsx)(i.code,{children:"buildConfig.format"})}),"."]}),"\n",(0,r.jsxs)(i.li,{children:["How the output type file is handled: the corresponding API is ",(0,r.jsx)(i.a,{href:"/api/config/build-config#dts",children:(0,r.jsx)(i.code,{children:"buildConfig.dts"})}),"."]}),"\n",(0,r.jsxs)(i.li,{children:["How the sourceMap of the artifact is handled: the corresponding API is ",(0,r.jsx)(i.a,{href:"/api/config/build-config#sourcemap",children:(0,r.jsx)(i.code,{children:"buildConfig.sourceMap"})}),"."]}),"\n",(0,r.jsxs)(i.li,{children:["The input (or source file) corresponding to the output: the corresponding API is ",(0,r.jsx)(i.a,{href:"/api/config/build-config#input",children:(0,r.jsx)(i.code,{children:"buildConfig.input"})}),"."]}),"\n",(0,r.jsxs)(i.li,{children:["The directory of the output of the artifact: the corresponding API is ",(0,r.jsx)(i.a,{href:"/api/config/build-config#outdir",children:(0,r.jsx)(i.code,{children:"buildConfig.outDir"})}),"."]}),"\n",(0,r.jsxs)(i.li,{children:["Build source directory: the corresponding API is ",(0,r.jsx)(i.a,{href:"/api/config/build-config#sourcedir",children:(0,r.jsx)(i.code,{children:"buildConfig.sourceDir"})}),"."]}),"\n"]}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.strong,{children:"Common functions required for build artifacts include:"})}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsxs)(i.li,{children:["Alias: The corresponding API is ",(0,r.jsx)(i.a,{href:"/api/config/build-config#alias",children:(0,r.jsx)(i.code,{children:"buildConfig.alias"})}),"."]}),"\n",(0,r.jsxs)(i.li,{children:["Static resource handling: the corresponding API is ",(0,r.jsx)(i.a,{href:"/api/config/build-config#asset",children:(0,r.jsx)(i.code,{children:"buildConfig.asset"})}),"."]}),"\n",(0,r.jsxs)(i.li,{children:["Third-party dependency handling: The corresponding APIs are","\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsxs)(i.li,{children:[(0,r.jsx)(i.a,{href:"/api/config/build-config#autoexternal",children:(0,r.jsx)(i.code,{children:"buildConfig.autoExternal"})}),"."]}),"\n",(0,r.jsxs)(i.li,{children:[(0,r.jsx)(i.a,{href:"/api/config/build-config#externals",children:(0,r.jsx)(i.code,{children:"buildConfig.externals"})}),"."]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(i.li,{children:["Copy: The corresponding API is ",(0,r.jsx)(i.a,{href:"/api/config/build-config#copy",children:(0,r.jsx)(i.code,{children:"buildConfig.copy"})}),"."]}),"\n",(0,r.jsxs)(i.li,{children:["Global variable substitution: the corresponding API is ",(0,r.jsx)(i.a,{href:"/api/config/build-config#define",children:(0,r.jsx)(i.code,{children:"buildConfig.define"})}),"."]}),"\n",(0,r.jsxs)(i.li,{children:["Specify ",(0,r.jsx)(i.a,{href:"https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html",target:"_blank",rel:"noopener noreferrer",children:"JSX"})," compilation method, the corresponding API is [",(0,r.jsx)(i.code,{children:"buildConfig.jsx"}),"](/api/config/ build-config#jsx)."]}),"\n"]}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.strong,{children:"Some advanced properties or less frequently used functions:"})}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsxs)(i.li,{children:["Product code compression: The corresponding API is ",(0,r.jsx)(i.a,{href:"/api/config/build-config#minify",children:(0,r.jsx)(i.code,{children:"buildConfig.minify"})}),"."]}),"\n",(0,r.jsxs)(i.li,{children:["Code splitting: ",(0,r.jsx)(i.a,{href:"/api/config/build-config#splitting",children:(0,r.jsx)(i.code,{children:"buildConfig.splitting"})})]}),"\n",(0,r.jsxs)(i.li,{children:["Specify whether the build artifacts is for the NodeJS environment or the browser environment: the corresponding API is ",(0,r.jsx)(i.a,{href:"/api/config/build-config#platform",children:(0,r.jsx)(i.code,{children:"buildConfig.platform"})}),"."]}),"\n",(0,r.jsxs)(i.li,{children:["umd product-related.","\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsxs)(i.li,{children:["Specifies the global variables imported externally to the umd product: the corresponding API is ",(0,r.jsx)(i.a,{href:"/api/config/build-config#umdglobals",children:(0,r.jsx)(i.code,{children:"buildConfig.umdGlobals"})}),"."]}),"\n",(0,r.jsxs)(i.li,{children:["Specify the module name of the umd product: the corresponding API is ",(0,r.jsx)(i.a,{href:"/api/config/build-config#umdmodulename",children:(0,r.jsx)(i.code,{children:"buildConfig.umdModuleName"})}),"."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(i.p,{children:"In addition to the above categories, frequently asked questions and best practices about these APIs can be found at the following links"}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsx)(i.li,{children:(0,r.jsxs)(i.a,{href:"/guide/advance/in-depth-about-build#bundle--bundleless",children:["About ",(0,r.jsx)(i.code,{children:"bundle"})," and ",(0,r.jsx)(i.code,{children:"bundleless"}),"?"]})}),"\n",(0,r.jsx)(i.li,{children:(0,r.jsxs)(i.a,{href:"/guide/advance/in-depth-about-build#input--sourcedir",children:["About ",(0,r.jsx)(i.code,{children:"input"})," and ",(0,r.jsx)(i.code,{children:"sourceDir"})]})}),"\n",(0,r.jsxs)(i.li,{children:[(0,r.jsx)(i.a,{href:"/guide/advance/in-depth-about-build#dts",children:"About d.ts"}),"."]}),"\n",(0,r.jsx)(i.li,{children:(0,r.jsx)(i.a,{href:"/guide/advance/in-depth-about-build#define",children:"How to use define"})}),"\n",(0,r.jsx)(i.li,{children:(0,r.jsx)(i.a,{href:"/guide/advance/external-dependency",children:"How to handle third-party dependencies?"})}),"\n",(0,r.jsx)(i.li,{children:(0,r.jsx)(i.a,{href:"/guide/advance/copy",children:"How to use copy?"})}),"\n",(0,r.jsx)(i.li,{children:(0,r.jsx)(i.a,{href:"/guide/advance/build-umd",children:"How to use umd"})}),"\n",(0,r.jsx)(i.li,{children:(0,r.jsx)(i.a,{href:"/guide/advance/asset",children:"How to use asset"})}),"\n"]}),"\n",(0,r.jsxs)(i.h2,{id:"combining-configuration-and-presets",children:["Combining Configuration and Presets",(0,r.jsx)(i.a,{className:"header-anchor","aria-hidden":"true",href:"#combining-configuration-and-presets",children:"#"})]}),"\n",(0,r.jsxs)(i.p,{children:["Once we understand ",(0,r.jsx)(i.code,{children:"buildPreset"})," and ",(0,r.jsx)(i.code,{children:"buildConfig"}),", we can use them together."]}),"\n",(0,r.jsxs)(i.p,{children:["In a real project, we can use ",(0,r.jsx)(i.code,{children:"buildPreset"})," to quickly get a set of default build configurations. If you need to customise it, you can use ",(0,r.jsx)(i.code,{children:"buildConfig"})," to override and extend it."]}),"\n",(0,r.jsx)(i.p,{children:"The extension logic is as follows."}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsxs)(i.li,{children:["When ",(0,r.jsx)(i.code,{children:"buildConfig"})," is an array, new configuration items are added to the original preset."]}),"\n"]}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{className:"language-ts",meta:'title="modern.config.ts"',children:"import { moduleTools, defineConfig } from '@modern-js/module-tools';\n\nexport default defineConfig({\n plugins: [moduleTools()],\n buildPreset: 'npm-library',\n buildConfig: [\n {\n format: 'iife',\n target: 'es2020',\n outDir: '. /dist/global'\n }\n ]\n});\n"})}),"\n",(0,r.jsxs)(i.p,{children:["This will generate an additional IIFE-formatted product that supports up to ES2020 syntax on top of the original preset, in the ",(0,r.jsx)(i.code,{children:"dist/global"})," directory under the project."]}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsxs)(i.li,{children:["When ",(0,r.jsx)(i.code,{children:"buildConfig"})," is an object, the configuration items in the object are overwritten in the preset."]}),"\n"]}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{className:"language-ts",meta:'title="modern.config.ts"',children:"import { moduleTools, defineConfig } from '@modern-js/module-tools';\nexport default defineConfig({\n plugins: [moduleTools()],\n buildPreset: 'npm-library',\n buildConfig: {\n sourceMap: true,\n },\n}).\n"})}),"\n",(0,r.jsx)(i.p,{children:"This will cause a sourceMap file to be generated for each build task."})]})}function d(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:i}=Object.assign({},(0,s.ah)(),e.components);return i?(0,r.jsx)(i,{...e,children:(0,r.jsx)(o,{...e})}):o(e)}let t=d;d.__RSPRESS_PAGE_META={},d.__RSPRESS_PAGE_META["en%2Fguide%2Fbasic%2Fmodify-output-product.md"]={toc:[{text:"Default output artifacts",id:"default-output-artifacts",depth:2},{text:"buildPreset",id:"buildpreset",depth:2},{text:"buildConfig",id:"buildconfig",depth:2},{text:"Combining Configuration and Presets",id:"combining-configuration-and-presets",depth:2}],title:"Modify the output",frontmatter:{sidebar_position:3}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_modern_js_module_tools_docs=self.webpackChunk_modern_js_module_tools_docs||[]).push([["7837"],{4520:function(t,e,n){n.r(e),n.d(e,{default:function(){return c}});var o=n(8093),s=n(5878);function r(t){return(0,o.jsx)(o.Fragment,{})}function _(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:e}=Object.assign({},(0,s.ah)(),t.components);return e?(0,o.jsx)(e,{...t,children:(0,o.jsx)(r,{...t})}):r(t)}let c=_;_.__RSPRESS_PAGE_META={},_.__RSPRESS_PAGE_META["en%2Fcomponents%2Ffaq-storybook.mdx"]={toc:[],title:"",frontmatter:{}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_modern_js_module_tools_docs=self.webpackChunk_modern_js_module_tools_docs||[]).push([["8040"],{6536:function(e,n,r){r.r(n),r.d(n,{default:function(){return c}});var o=r(8093),s=r(5878);function d(e){let n=Object.assign({h1:"h1",a:"a",p:"p",ul:"ul",li:"li",h2:"h2",h3:"h3",pre:"pre",code:"code",div:"div",blockquote:"blockquote",strong:"strong",h4:"h4"},(0,s.ah)(),e.components);return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(n.h1,{id:"使用-storybook",children:["使用 Storybook",(0,o.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#使用-storybook",children:"#"})]}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.a,{href:"https://storybook.js.org/",target:"_blank",rel:"noopener noreferrer",children:"Storybook"})," 是一个专门用于组件调试的工具,它围绕着组件开发提供了:"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"丰富多样的调试能力"}),"\n",(0,o.jsx)(n.li,{children:"可与一些测试工具结合使用"}),"\n",(0,o.jsx)(n.li,{children:"可重复使用的文档内容"}),"\n",(0,o.jsx)(n.li,{children:"可分享能力"}),"\n",(0,o.jsx)(n.li,{children:"工作流程自动化"}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"在使用 Storybook 时,难免会遇到各种配置问题,需要手动配置 Babel 插件,手动配置 Webpack 去支持 less,sass 等。\nModern.js 集成了 Storybook,这对于我们开发 Storybook 项目来说极大地简化了配置工作。"}),"\n",(0,o.jsxs)(n.h2,{id:"v7-推荐",children:["V7 (推荐)",(0,o.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#v7-推荐",children:"#"})]}),"\n",(0,o.jsxs)(n.h3,{id:"开启-storybook",children:["开启 Storybook",(0,o.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#开启-storybook",children:"#"})]}),"\n",(0,o.jsx)(n.p,{children:"可以直接使用如下命令开启 Storybook 功能。"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:"$ npx modern new\n? 请选择你想要的操作 启用可选功能\n? 请选择功能名称 启用「Storybook」V7\n"})}),"\n",(0,o.jsx)(n.p,{children:"该命令会创建好 Storybook 常用的模版,包括"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["创建配置文件夹 ",(0,o.jsx)(n.code,{children:".storybook"}),",以及默认配置文件 ",(0,o.jsx)(n.code,{children:".storybook/main.ts"})]}),"\n",(0,o.jsx)(n.li,{children:"创建 stories 组件示例"}),"\n",(0,o.jsx)(n.li,{children:"更新 package.json,新增依赖 @storybook/addon-essential 和 @modern-js/storybook,以及创建 storybook 相关脚本。"}),"\n"]}),"\n",(0,o.jsxs)(n.h3,{id:"开启产物调试",children:["开启产物调试",(0,o.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#开启产物调试",children:"#"})]}),"\n",(0,o.jsx)(n.p,{children:"事实上,Modern.js Module 是基于 esbuild 实现的,而 Storybook 使用 Webpack 作为默认构建工具,二者的配置无法完全兼容,\n所以这里我们推荐先对组件进行构建,然后在 stories 里引入组件产物。"}),"\n",(0,o.jsx)(n.p,{children:"引入组件产物的方式非常简单,假设你的模块导出了一个 Button 组件,那么在 stories 里可以这样使用:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-ts",meta:'filename="stories/index.stories.tsx"',children:"import { Button } from '.';\n\nexport const YourStory = () => <Button />;\n\nexport default {\n title: 'Your Stories',\n};\n"})}),"\n",(0,o.jsx)(n.p,{children:"如果想要更新组件,则可以在启动 Storybook 前启动监听模式的构建:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:"modern build --watch\n"})}),"\n",(0,o.jsxs)(n.div,{className:"rspress-directive info",children:[(0,o.jsx)(n.div,{className:"rspress-directive-title",children:"INFO"}),(0,o.jsxs)(n.div,{className:"rspress-directive-content",children:[(0,o.jsx)(n.p,{children:"在开发过程中,可能会遇到无法实时获得类型定义的情况。因为只有当保存代码后,产物目录下的类型文件才会更新。此时:"}),"\n",(0,o.jsxs)(n.p,{children:["对于 ",(0,o.jsx)(n.code,{children:"pnpm"})," 的项目,可以按照下面的内容对 ",(0,o.jsx)(n.code,{children:"package.json"})," 进行修改:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-ts",children:'{\n "name": "foo",\n "main": "./dist/index.js",\n "types": "./src/index.ts",\n "publishConfig": {\n "types": "./dist/index.d.ts",\n }\n}\n'})}),"\n",(0,o.jsxs)(n.blockquote,{children:["\n",(0,o.jsxs)(n.p,{children:["关于 pnpm 的 ",(0,o.jsx)(n.code,{children:"publishConfig"})," 的使用,可以阅读下面这个",(0,o.jsx)(n.a,{href:"https://pnpm.io/package_json#publishconfig",target:"_blank",rel:"noopener noreferrer",children:"链接"}),"。"]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["而对于 npm 和 Yarn 的项目,则只能通过手动的方式在",(0,o.jsx)(n.strong,{children:"开发阶段"}),"和",(0,o.jsx)(n.strong,{children:"发布阶段"}),"对 ",(0,o.jsx)(n.code,{children:"package.json"})," 的 ",(0,o.jsx)(n.code,{children:"types"})," 的值进行修改。\n"]})]})]}),"\n",(0,o.jsxs)(n.h3,{id:"开启-rspack-构建",children:["开启 Rspack 构建",(0,o.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#开启-rspack-构建",children:"#"})]}),"\n",(0,o.jsx)(n.p,{children:"Rspack 构建速度非常快,只需要如下配置即可使用 Rspack 作为构建工具。"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-diff",meta:"filename='.storybook/main.js'",children:"const config = {\n framework: {\n name: '@modern-js/storybook',\n options: {\n- bundler: 'webpack'\n+ bundler: 'rspack'\n },\n },\n typescript: {\n- reactDocgen: 'react-docgen-typescript'\n+ reactDocgen: 'react-docgen'\n }\n};\n\nexport default config;\n"})}),"\n",(0,o.jsx)(n.p,{children:"注意上面配置中,更改了 reactDocgen 配置,因为 Rspack 目前还不支持 @storybook/react-docgen-typescript-plugin。"}),"\n",(0,o.jsxs)(n.h3,{id:"配置",children:["配置",(0,o.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#配置",children:"#"})]}),"\n",(0,o.jsxs)(n.p,{children:["在 ",(0,o.jsx)(n.code,{children:".storybook/main.js"})," 中包含一些独有的配置。"]}),"\n",(0,o.jsxs)(n.h4,{id:"bundler",children:["bundler",(0,o.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#bundler",children:"#"})]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"类型"}),": ",(0,o.jsx)(n.code,{children:"'webpack' | 'rspack'"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"默认值"}),": ",(0,o.jsx)(n.code,{children:"webpack"})]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"指定底层打包工具使用 Webpack 还是 Rspack。"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-javascript",meta:"filename='.storybook/main.js'",children:"const config = {\n framework: {\n name: '@modern-js/storybook',\n options: {\n bundler: 'rspack',\n },\n },\n};\n\nexport default config;\n"})}),"\n",(0,o.jsxs)(n.h4,{id:"builderconfig",children:["builderConfig",(0,o.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#builderconfig",children:"#"})]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"类型"}),": ",(0,o.jsx)(n.code,{children:"BuilderConfig"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"默认值"}),": ",(0,o.jsx)(n.code,{children:"undefined"})]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["Modern.js 的 Storybook 构建能力由 ",(0,o.jsx)(n.a,{href:"https://rsbuild.dev/",target:"_blank",rel:"noopener noreferrer",children:"Rsbuild"})," 提供,可通过 builderConfig 修改 Rsbuild 构建配置。"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-javascript",meta:"filename='.storybook/main.js'",children:"const config = {\n framework: {\n name: '@modern-js/storybook',\n options: {\n builderConfig: {\n alias: {\n react: require.resolve('react'),\n 'react-dom': require.resolve('react-dom'),\n },\n },\n },\n },\n};\n\nexport default config;\n"})}),"\n",(0,o.jsxs)(n.h3,{id:"命令行",children:["命令行",(0,o.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#命令行",children:"#"})]}),"\n",(0,o.jsx)(n.p,{children:"@modern-js/storybook 代理了部分 storybook cli 的命令。"}),"\n",(0,o.jsxs)(n.h4,{id:"storybook-dev",children:["storybook dev",(0,o.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#storybook-dev",children:"#"})]}),"\n",(0,o.jsxs)(n.p,{children:["启动 Storybook,查看",(0,o.jsx)(n.a,{href:"https://storybook.js.org/docs/react/api/cli-options#dev",target:"_blank",rel:"noopener noreferrer",children:"详情"})]}),"\n",(0,o.jsxs)(n.h4,{id:"storybook-build",children:["storybook build",(0,o.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#storybook-build",children:"#"})]}),"\n",(0,o.jsxs)(n.p,{children:["对 Storybook 进行生产环境构建,查看",(0,o.jsx)(n.a,{href:"https://storybook.js.org/docs/react/api/cli-options#build",target:"_blank",rel:"noopener noreferrer",children:"详情"})]}),"\n",(0,o.jsxs)(n.h3,{id:"配置文件",children:["配置文件",(0,o.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#配置文件",children:"#"})]}),"\n",(0,o.jsx)(n.p,{children:"配置文件中除了 Rsbuild 配置还包含一个额外的字段,builderPlugins,方便使用 Rsbuild 插件,例如启用 SWC 编译。"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-typescript",meta:"filename='modern.config.ts'",children:"import { defineConfig } from '@modern-js/storybook';\nimport { pluginSwc } from '@rsbuild/plugin-webpack-swc';\n\nconst config = defineConfig({\n builderPlugins: [pluginSwc()],\n});\n\nexport default config;\n"})}),"\n",(0,o.jsxs)(n.h2,{id:"从-v6-迁移至-v7",children:["从 V6 迁移至 V7",(0,o.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#从-v6-迁移至-v7",children:"#"})]}),"\n",(0,o.jsx)(n.p,{children:"我们对于两个版本的支持方式不同,因此如果你是从 V6 迁移至 V7 的用户,我们希望你也按上述方式使用 V7,同时做以下调整:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["配置文件:将原来 ",(0,o.jsx)(n.code,{children:"root/config/storybook/main.(j|t)s"})," 里的自定义配置(如果有)迁移到新的 ",(0,o.jsx)(n.code,{children:"root/.storybook/main.(j|t)s"}),"。"]}),"\n",(0,o.jsxs)(n.li,{children:["依赖:升级 ",(0,o.jsx)(n.code,{children:"@storybook/addon-*"})," 系列依赖(如果有)到 7 版本,并删除 ",(0,o.jsx)(n.code,{children:"@modern-js/plugin-storybook"})," 依赖。"]}),"\n",(0,o.jsxs)(n.li,{children:["命令: 将原来 ",(0,o.jsx)(n.code,{children:"edenx dev storybook"})," 和 ",(0,o.jsx)(n.code,{children:"edenx build --platform"})," 命令删除,如果习惯了原来的 ",(0,o.jsx)(n.code,{children:"pnpm run dev"})," 的调用方式,可以\n将其替换成 ",(0,o.jsx)(n.code,{children:"storybook dev -p 6006"})," 和 ",(0,o.jsx)(n.code,{children:"storybook build"}),"。"]}),"\n",(0,o.jsxs)(n.li,{children:["modern.config.(j|t)s : 删除 ",(0,o.jsx)(n.code,{children:"@modern-js/plugin-storybook"})," 插件的注册。"]}),"\n"]}),"\n",(0,o.jsxs)(n.h2,{id:"v6-legacy",children:["V6 (legacy)",(0,o.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#v6-legacy",children:"#"})]}),"\n",(0,o.jsxs)(n.p,{children:["从 ",(0,o.jsx)(n.code,{children:"2.40.0"})," 版本开始,",(0,o.jsx)(n.code,{children:"@modern-js/plugin-storybook"}),"将停止迭代。建议使用 V7 版本。\n如果你的 ",(0,o.jsx)(n.code,{children:"@modern-js/module-tools"})," 版本低于 ",(0,o.jsx)(n.code,{children:"2.40.0"}),",可以按照以下方式使用 Storybook V6:"]}),"\n",(0,o.jsxs)(n.h3,{id:"开启-storybook-1",children:["开启 Storybook",(0,o.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#开启-storybook-1",children:"#"})]}),"\n",(0,o.jsx)(n.p,{children:"可以直接使用如下命令开启 Storybook 功能。"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:"$ npx modern new\n? 请选择你想要的操作 启用可选功能\n? 请选择功能名称 启用「Storybook」\n"})}),"\n",(0,o.jsx)(n.p,{children:"该命令会创建好 Storybook 常用的模版,包括"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"创建 stories 组件示例"}),"\n",(0,o.jsxs)(n.li,{children:["更新 package.json,新增依赖 @modern-js/plugin-storybook,以及添加 ",(0,o.jsx)(n.code,{children:"pnpm dev storybook"})," 等相关脚本。"]}),"\n"]}),"\n",(0,o.jsxs)(n.h3,{id:"配置-storybook",children:["配置 Storybook",(0,o.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#配置-storybook",children:"#"})]}),"\n",(0,o.jsxs)(n.p,{children:["Storybook 官方通过一个名为 ",(0,o.jsx)(n.code,{children:".storybook"})," 的文件夹来进行项目配置,其中包含各种配置文件。",(0,o.jsxs)(n.strong,{children:["在 Modern.js Module 中,可以在项目的 ",(0,o.jsx)(n.code,{children:"config/storybook"})," 目录下增加 Storybook 配置文件。"]})]}),"\n",(0,o.jsx)(n.p,{children:"关于 Storybook 各种配置文件的使用方式,可以查看下面的链接:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"https://storybook.js.org/docs/react/configure/overview",target:"_blank",rel:"noopener noreferrer",children:"Configure Storybook"})}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.strong,{children:"不过这在模块项目里使用时存在一些限制"}),":"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["不能修改 Story 文件存放的位置,即无法在 ",(0,o.jsx)(n.code,{children:"main.js"})," 文件里修改 ",(0,o.jsx)(n.code,{children:"stories"})," 配置。"]}),"\n",(0,o.jsxs)(n.li,{children:["不能修改 Webpack 和 Babel 相关的配置,即无法在 ",(0,o.jsx)(n.code,{children:"main.js"})," 文件里修改 ",(0,o.jsx)(n.code,{children:"webpackFinal"})," 和 ",(0,o.jsx)(n.code,{children:"babel"})," 配置。"]}),"\n"]}),"\n",(0,o.jsxs)(n.h3,{id:"构建-storybook-产物",children:["构建 Storybook 产物",(0,o.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#构建-storybook-产物",children:"#"})]}),"\n",(0,o.jsx)(n.p,{children:"除了可以对组件或者普通的模块进行 Storybook 调试,还可以通过下面的命令来执行 Storybook 的构建任务。"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:"modern build --platform storybook\n"})}),"\n",(0,o.jsxs)(n.p,{children:["构建完成后,可以在 ",(0,o.jsx)(n.code,{children:"dist/storybook-static"})," 目录看到构建产物文件。"]})]})}function i(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,s.ah)(),e.components);return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}let c=i;i.__RSPRESS_PAGE_META={},i.__RSPRESS_PAGE_META["zh%2Fguide%2Fbasic%2Fusing-storybook.mdx"]={toc:[{text:"V7 (推荐)",id:"v7-推荐",depth:2},{text:"开启 Storybook",id:"开启-storybook",depth:3},{text:"开启产物调试",id:"开启产物调试",depth:3},{text:"开启 Rspack 构建",id:"开启-rspack-构建",depth:3},{text:"配置",id:"配置",depth:3},{text:"bundler",id:"bundler",depth:4},{text:"builderConfig",id:"builderconfig",depth:4},{text:"命令行",id:"命令行",depth:3},{text:"storybook dev",id:"storybook-dev",depth:4},{text:"storybook build",id:"storybook-build",depth:4},{text:"配置文件",id:"配置文件",depth:3},{text:"从 V6 迁移至 V7",id:"从-v6-迁移至-v7",depth:2},{text:"V6 (legacy)",id:"v6-legacy",depth:2},{text:"开启 Storybook",id:"开启-storybook-1",depth:3},{text:"配置 Storybook",id:"配置-storybook",depth:3},{text:"构建 Storybook 产物",id:"构建-storybook-产物",depth:3}],title:"使用 Storybook",frontmatter:{sidebar_position:5}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_modern_js_module_tools_docs=self.webpackChunk_modern_js_module_tools_docs||[]).push([["8085"],{9322:function(e,n,t){t.r(n),t.d(n,{default:function(){return u}});var o=t(8093),s=t(5878);function _(e){return(0,o.jsx)(o.Fragment,{})}function r(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,s.ah)(),e.components);return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(_,{...e})}):_(e)}let u=r;r.__RSPRESS_PAGE_META={},r.__RSPRESS_PAGE_META["en%2Fcomponents%2Fpublish-emo.mdx"]={toc:[],title:"",frontmatter:{}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_modern_js_module_tools_docs=self.webpackChunk_modern_js_module_tools_docs||[]).push([["8098"],{9694:function(e,n,t){t.r(n),t.d(n,{default:function(){return d}});var r=t(8093),i=t(5878),o=t(8078);function s(e){let n=Object.assign({h1:"h1",a:"a",p:"p",h2:"h2",h3:"h3",pre:"pre",code:"code",div:"div",ul:"ul",li:"li",strong:"strong"},(0,i.ah)(),e.components);return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.h1,{id:"banner-plugin",children:["Banner Plugin",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#banner-plugin",children:"#"})]}),"\n",(0,r.jsx)(n.p,{children:"Provide the ability to inject content at the top and bottom of each JS and CSS file."}),"\n",(0,r.jsxs)(n.h2,{id:"quick-start",children:["Quick Start",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#quick-start",children:"#"})]}),"\n",(0,r.jsxs)(n.h3,{id:"install",children:["Install",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#install",children:"#"})]}),"\n","\n",(0,r.jsx)(o.SU,{command:"add @modern-js/plugin-module-banner -D"}),"\n",(0,r.jsxs)(n.h3,{id:"register",children:["Register",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#register",children:"#"})]}),"\n",(0,r.jsx)(n.p,{children:"You can install the plugin with the following command:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"import { moduleTools, defineConfig } from '@modern-js/module-tools';\nimport { modulePluginBanner } from '@modern-js/plugin-module-banner';\n\nexport default defineConfig({\n plugins: [\n moduleTools(),\n modulePluginBanner({\n banner: {\n js: '//comment',\n css: '/*comment*/',\n },\n }),\n ],\n});\n"})}),"\n",(0,r.jsxs)(n.div,{className:"rspress-directive tip",children:[(0,r.jsx)(n.div,{className:"rspress-directive-title",children:"TIP"}),(0,r.jsx)(n.div,{className:"rspress-directive-content",children:(0,r.jsxs)(n.p,{children:["Note: CSS comments do not support the ",(0,r.jsx)(n.code,{children:"//comment"})," syntax. Refer to ",(0,r.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Web/CSS/Comments",target:"_blank",rel:"noopener noreferrer",children:'"CSS Comments"'}),"\n"]})})]}),"\n",(0,r.jsxs)(n.h2,{id:"example",children:["Example",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#example",children:"#"})]}),"\n",(0,r.jsxs)(n.h3,{id:"add-copyright-information-at-the-top-of-a-js-file",children:["Add copyright information at the top of a JS file",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#add-copyright-information-at-the-top-of-a-js-file",children:"#"})]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"import { modulePluginBanner } from '@modern-js/plugin-module-banner';\nimport { moduleTools, defineConfig } from '@modern-js/module-tools';\n\nconst copyRight = `/*\n \xa9 Copyright 2020 example.com or one of its affiliates.\n * Some Sample Copyright Text Line\n * Some Sample Copyright Text Line\n * Some Sample Copyright Text Line\n * Some Sample Copyright Text Line\n * Some Sample Copyright Text Line\n * Some Sample Copyright Text Line\n*/`;\n\nexport default defineConfig({\n plugins: [\n moduleTools(),\n modulePluginBanner({\n banner: {\n js: copyRight,\n },\n }),\n ],\n});\n"})}),"\n",(0,r.jsxs)(n.h2,{id:"configuration",children:["Configuration",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#configuration",children:"#"})]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.strong,{children:"Type"})}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"type BannerOptions = {\n banner: {\n js?: string;\n css?: string;\n };\n footer?: {\n js?: string;\n css?: string;\n };\n};\n"})}),"\n",(0,r.jsxs)(n.h3,{id:"banner",children:["banner",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#banner",children:"#"})]}),"\n",(0,r.jsx)(n.p,{children:"Add content at the top."}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"banner.js"}),": Add content at the top of a JS file."]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"banner.css"}),": Add content at the top of a CSS file."]}),"\n"]}),"\n",(0,r.jsxs)(n.h3,{id:"footer",children:["footer",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#footer",children:"#"})]}),"\n",(0,r.jsx)(n.p,{children:"Add content at the bottom."}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"footer.js"}),": Add content at the bottom of a JS file."]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"footer.css"}),": Add content at the bottom of a CSS file."]}),"\n"]})]})}function a(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,i.ah)(),e.components);return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(s,{...e})}):s(e)}let d=a;a.__RSPRESS_PAGE_META={},a.__RSPRESS_PAGE_META["en%2Fplugins%2Fofficial-list%2Fplugin-banner.mdx"]={toc:[{text:"Quick Start",id:"quick-start",depth:2},{text:"Install",id:"install",depth:3},{text:"Register",id:"register",depth:3},{text:"Example",id:"example",depth:2},{text:"Add copyright information at the top of a JS file",id:"add-copyright-information-at-the-top-of-a-js-file",depth:3},{text:"Configuration",id:"configuration",depth:2},{text:"banner",id:"banner",depth:3},{text:"footer",id:"footer",depth:3}],title:"Banner Plugin",frontmatter:{}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_modern_js_module_tools_docs=self.webpackChunk_modern_js_module_tools_docs||[]).push([["8134"],{2323:function(e,n,r){r.r(n),r.d(n,{default:function(){return d}});var s=r(8093),o=r(5878);function t(e){let n=Object.assign({h1:"h1",a:"a",p:"p",img:"img",strong:"strong"},(0,o.ah)(),e.components);return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.h1,{id:"为什么需要-modernjs-module",children:["为什么需要 Modern.js Module",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#为什么需要-modernjs-module",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"大家可能都经历过:从零开始开发一个组件库或者工具库的过程中,我们不仅要考虑项目本身的代码逻辑如何编写,还要考虑项目的构建、调试、测试、代码格式化等等和代码逻辑无关的事情。"}),"\n",(0,s.jsxs)(n.p,{children:["比如说,当我们考虑构建模块项目的代码是使用什么构建工具的时候,在之前我们可能会考虑使用 ",(0,s.jsx)(n.a,{href:"https://webpack.js.org/",target:"_blank",rel:"noopener noreferrer",children:"webpack"})," 还是 ",(0,s.jsx)(n.a,{href:"https://rollupjs.org/guide/en/",target:"_blank",rel:"noopener noreferrer",children:"Rollup"}),",然而现在的话,也许还会考虑是使用 ",(0,s.jsx)(n.a,{href:"https://esbuild.github.io/",target:"_blank",rel:"noopener noreferrer",children:"esbuild"})," 还是 ",(0,s.jsx)(n.a,{href:"https://swc.rs/",target:"_blank",rel:"noopener noreferrer",children:"SWC"}),"。"]}),"\n",(0,s.jsx)(n.p,{children:"无论选择哪个构建工具,这对于没有熟练掌握这些构建工具使用方式的开发者来说,是需要一定的成本去学习的。即使想要快速使用,也会需要花费大量的时间和精力。"}),"\n",(0,s.jsx)(n.p,{children:"而除了构建这件事情以外,像为项目提供调试工具、支持测试能力、增加代码格式校验等等,对于一个新手来说都有可能需要花费很长的时间和精力了解或者掌握它们,并且真正的服务于当前的项目中。"}),"\n",(0,s.jsx)(n.p,{children:"而为了保证代码质量以及项目的完整性,我们往往是需要做这些与代码逻辑实现无关的事情。然而这些事情很有可能会影响整体的项目开发进度,降低开发者的开发体验,会让开发者感觉模块项目的开发门槛很高。"}),"\n",(0,s.jsx)(n.p,{children:"如果说每次开发一个模块类型的项目都需要经历一遍这些工作准备的话,那么基本上刚开始开发的时间会大部分花费在这些与代码实现无关的事情上。如果能够提供一个模块工程解决方案,它能够帮助开发者解决项目工程上的事情,让开发者可以更专注于代码的实现上,那么这将会大大提升模块类型项目的开发体验。"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:"https://lf3-static.bytednsdoc.com/obj/eden-cn/uhbfnupenuhf/module-tools/why-module-solution.png",alt:"没有使用工程方案对比使用工程方案"})}),"\n",(0,s.jsxs)(n.p,{children:["Modern.js 为了让开发模块类型的项目更简单、解决上述提到的问题,提供了模块工程解决方案,并且通过 Modern.js Module 提供了主要的功能。",(0,s.jsx)(n.strong,{children:"Modern.js Module 可以理解为是一个专门用于模块类型项目开发的工具"}),"。"]})]})}function l(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,o.ah)(),e.components);return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(t,{...e})}):t(e)}let d=l;l.__RSPRESS_PAGE_META={},l.__RSPRESS_PAGE_META["zh%2Fguide%2Fintro%2Fwhy-module-engineering-solution.md"]={toc:[],title:"为什么需要 Modern.js Module",frontmatter:{sidebar_position:2}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_modern_js_module_tools_docs=self.webpackChunk_modern_js_module_tools_docs||[]).push([["8158"],{5775:function(e,n,i){i.r(n),i.d(n,{default:function(){return d}});var r=i(8093),s=i(5878);function l(e){let n=Object.assign({h1:"h1",a:"a",p:"p",ul:"ul",li:"li",strong:"strong",code:"code",h2:"h2",h3:"h3",pre:"pre",h4:"h4"},(0,s.ah)(),e.components);return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.h1,{id:"plugins",children:["plugins",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#plugins",children:"#"})]}),"\n",(0,r.jsx)(n.p,{children:"This chapter describes the configuration of the registered Modern.js Module plugin."}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Type"}),": ",(0,r.jsx)(n.code,{children:"ModuleToolsPlugin[]"})]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Default"}),": ",(0,r.jsx)(n.code,{children:"undefined"})]}),"\n"]}),"\n",(0,r.jsxs)(n.h2,{id:"plugin-execution-order",children:["Plugin Execution Order",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#plugin-execution-order",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["By default, custom plugins are executed in the order specified in the ",(0,r.jsx)(n.code,{children:"plugins"})," array. The execution of built-in plugins provided by Modern.js Module happens before the execution of custom plugins."]}),"\n",(0,r.jsxs)(n.p,{children:["When plugins use fields that control the execution order, such as ",(0,r.jsx)(n.code,{children:"pre"})," and ",(0,r.jsx)(n.code,{children:"post"}),", the execution order is adjusted based on the declared fields. For more information, please refer to the ",(0,r.jsx)(n.a,{href:"https://modernjs.dev/en/guides/topic-detail/framework-plugin/relationship",target:"_blank",rel:"noopener noreferrer",children:"Relationship Between Plugins"})," guide."]}),"\n",(0,r.jsxs)(n.h2,{id:"developing-plugins",children:["Developing Plugins",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#developing-plugins",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["To learn how to write plugins, please refer to the ",(0,r.jsx)(n.a,{href:"/plugins/guide/getting-started",children:"Plugin Writing Guide"}),"."]}),"\n",(0,r.jsxs)(n.h2,{id:"example",children:["Example",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#example",children:"#"})]}),"\n",(0,r.jsxs)(n.h3,{id:"using-plugins-from-npm",children:["Using Plugins from npm",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#using-plugins-from-npm",children:"#"})]}),"\n",(0,r.jsx)(n.p,{children:"To use plugins from npm, you need to install them using a package manager and import them in your configuration file."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",meta:'title="modern.config.ts"',children:"import { myPlugin } from 'my-plugin';\n\nexport default defineConfig({\n plugins: [myPlugin()],\n});\n"})}),"\n",(0,r.jsxs)(n.h4,{id:"using-local-plugins",children:["Using Local Plugins",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#using-local-plugins",children:"#"})]}),"\n",(0,r.jsx)(n.p,{children:"To use plugins from a local code repository, you can directly import them using a relative path."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",meta:'title="modern.config.ts"',children:"import { myPlugin } from './plugins/myPlugin';\n\nexport default defineConfig({\n plugins: [myPlugin()],\n});\n"})}),"\n",(0,r.jsxs)(n.h3,{id:"plugin-configuration",children:["Plugin Configuration",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#plugin-configuration",children:"#"})]}),"\n",(0,r.jsx)(n.p,{children:"If a plugin provides custom configuration options, you can pass the configuration through the plugin function's parameters."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",meta:'title="modern.config.ts"',children:"import { myPlugin } from 'my-plugin';\n\nexport default defineConfig({\n plugins: [\n myPlugin({\n foo: 1,\n bar: 2,\n }),\n ],\n});\n"})})]})}function o(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,s.ah)(),e.components);return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}let d=o;o.__RSPRESS_PAGE_META={},o.__RSPRESS_PAGE_META["en%2Fapi%2Fconfig%2Fplugins.md"]={toc:[{text:"Plugin Execution Order",id:"plugin-execution-order",depth:2},{text:"Developing Plugins",id:"developing-plugins",depth:2},{text:"Example",id:"example",depth:2},{text:"Using Plugins from npm",id:"using-plugins-from-npm",depth:3},{text:"Using Local Plugins",id:"using-local-plugins",depth:4},{text:"Plugin Configuration",id:"plugin-configuration",depth:3}],title:"plugins",frontmatter:{sidebar_position:4}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_modern_js_module_tools_docs=self.webpackChunk_modern_js_module_tools_docs||[]).push([["8214"],{3021:function(t,e,n){n.r(e),n.d(e,{default:function(){return u}});var o=n(8093),r=n(5878);function s(t){return(0,o.jsx)(o.Fragment,{})}function _(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:e}=Object.assign({},(0,r.ah)(),t.components);return e?(0,o.jsx)(e,{...t,children:(0,o.jsx)(s,{...t})}):s(t)}let u=_;_.__RSPRESS_PAGE_META={},_.__RSPRESS_PAGE_META["zh%2Fcomponents%2Ffaq-build-other.mdx"]={toc:[],title:"",frontmatter:{}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_modern_js_module_tools_docs=self.webpackChunk_modern_js_module_tools_docs||[]).push([["8233"],{9201:function(e,n,r){r.r(n),r.d(n,{default:function(){return l}});var s=r(8093),d=r(5878);function i(e){let n=Object.assign({h1:"h1",a:"a",h2:"h2",p:"p",strong:"strong",code:"code",pre:"pre",ul:"ul",li:"li",blockquote:"blockquote",div:"div",h3:"h3",h4:"h4"},(0,d.ah)(),e.components);return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.h1,{id:"开始之前",children:["开始之前",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#开始之前",children:"#"})]}),"\n",(0,s.jsxs)(n.h2,{id:"环境准备",children:["环境准备",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#环境准备",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["为了使用 Modern.js Module,首先需要 ",(0,s.jsx)(n.a,{href:"https://nodejs.org/zh/",target:"_blank",rel:"noopener noreferrer",children:"NodeJS"}),",我们推荐最新的",(0,s.jsx)(n.a,{href:"https://github.com/nodejs/Release",target:"_blank",rel:"noopener noreferrer",children:"长期维护版本"}),",并确保 Node 版本大于等于 ",(0,s.jsx)(n.strong,{children:"16.0.0"}),"。因为非稳定的 NodeJS 时常有一些 Bug,你可以使用 ",(0,s.jsx)(n.a,{href:"https://github.com/coreybutler/nvm-windows",target:"_blank",rel:"noopener noreferrer",children:"nvm-windows"})," 和 ",(0,s.jsx)(n.a,{href:"https://github.com/nvm-sh/nvm",target:"_blank",rel:"noopener noreferrer",children:"nvm"}),"(Mac / Linux)安装,这样你就可以方便地切换到不同的 NodeJS 版本,这些版本可能会用于不同的项目。"]}),"\n",(0,s.jsxs)(n.h2,{id:"初识-npm",children:["初识 npm",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#初识-npm",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["当 NodeJS 被安装后,你不仅可以在命令行中访问 ",(0,s.jsx)(n.code,{children:"node"})," 可执行程序,同时你也可以执行 ",(0,s.jsx)(n.code,{children:"npm"})," 命令。"]}),"\n",(0,s.jsx)(n.p,{children:"npm 是 NodeJS 的标准软件包管理器。它一开始的用途是用于下载和管理 NodeJS 包的依赖关系,但后来它逐渐变成为一个用于前端 JavaScript 的工具。"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsxs)(n.strong,{children:["如果你已经对 npm 和 npm 包的使用方式有所了解,那么可以直接跳到",(0,s.jsx)(n.a,{href:"/guide/basic/before-getting-started#npm-%E5%8C%85%E7%AE%A1%E7%90%86%E5%99%A8",children:"「npm 包管理器」"}),"部分。"]})}),"\n",(0,s.jsxs)(n.h2,{id:"npm-包类型项目",children:["npm 包类型项目",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#npm-包类型项目",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["那么什么是 npm 包类型的项目呢?当我们在一个空的项目目录下执行 ",(0,s.jsx)(n.code,{children:"npm init"})," 命令的时候,它会在当前目录下面创建一个文件名为 ",(0,s.jsx)(n.code,{children:"package.json"})," 的 JSON 文件。在创建过程中,我们需要填写包括但不限于 npm 包的名称、版本号、描述等等内容,这些填写的内容都会在生成的 ",(0,s.jsx)(n.code,{children:"package.json"})," 文件中找到:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "name": "npm-demo",\n "version": "1.0.0",\n "description": "",\n "main": "index.js",\n "scripts": {\n "test": "echo \\"Error: no test specified\\" && exit 1"\n },\n "author": "",\n "license": "ISC"\n}\n'})}),"\n",(0,s.jsxs)(n.p,{children:["此时这个包含了初始化后的 ",(0,s.jsx)(n.code,{children:"package.json"})," 文件的项目就是一个 npm 包类型的项目,你可以执行 ",(0,s.jsx)(n.code,{children:"npm publish"})," 命令将这个项目发布到 ",(0,s.jsx)(n.a,{href:"https://www.npmjs.com/",target:"_blank",rel:"noopener noreferrer",children:"npm Registry"}),"。"]}),"\n",(0,s.jsxs)(n.p,{children:["npm Registry 是一个 ",(0,s.jsx)(n.a,{href:"https://docs.npmjs.com/about-the-public-npm-registry",target:"_blank",rel:"noopener noreferrer",children:"npm 包存储的地方"}),",开发者们不仅可以将他们自己的 npm 包发布到 npm Registry,还可以通过 npm Registry 使用其他开发者发布的 npm 包。"]}),"\n",(0,s.jsx)(n.p,{children:"优质的 npm 包会有更多的人去使用,因为它不仅节省了很多代码实现的工作,同时也不容易让项目出现问题。"}),"\n",(0,s.jsxs)(n.h2,{id:"使用第三方-npm-包",children:["使用第三方 npm 包",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#使用第三方-npm-包",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["当要为初始化的项目增加第三方的 npm 包的时候,我们可以把这一过程叫做“为项目安装依赖”或是“为项目增加依赖”。在增加依赖之前,首先我们要特别了解一件事情 —— ",(0,s.jsx)(n.strong,{children:"npm 依赖的软件包类型"}),":"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:'"dependencies"'}),":一种是你的应用程序在生产环境中需要的软件包。"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:'"devDependencies"'}),":另一种是仅在本地开发和测试中需要的软件包。","\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)(n.p,{children:"软件包可以理解为是第三方的 npm 包。"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["你可以通过执行 ",(0,s.jsx)(n.code,{children:"npm install npm-package-name"})," 或者 ",(0,s.jsx)(n.code,{children:"npm add npm-package-name"})," 的方式来安装在",(0,s.jsx)(n.strong,{children:"生产环境中需要的软件包"}),",或者也可以在 ",(0,s.jsx)(n.code,{children:"package.json"})," 文件中手动的将需要安装的包和对应的",(0,s.jsx)(n.a,{href:"https://docs.npmjs.com/about-semantic-versioning",target:"_blank",rel:"noopener noreferrer",children:"语义化版本"}),"写在 ",(0,s.jsx)(n.code,{children:'"dependencies"'})," 里,并执行 ",(0,s.jsx)(n.code,{children:"npm install"})," 命令:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "name": "your-npm-project",\n "dependencies": {\n "npm-package-name": "0.1.0"\n }\n}\n'})}),"\n",(0,s.jsxs)(n.p,{children:["同理,你也可以执行 ",(0,s.jsx)(n.code,{children:"npm install npm-package-name --save-dev"})," 或 ",(0,s.jsx)(n.code,{children:"npm add npm-package-name --save-dev"})," 的方式来安装",(0,s.jsx)(n.strong,{children:"仅在本地开发和测试中需要的软件包"}),",或者也可以在 ",(0,s.jsx)(n.code,{children:"package.json"})," 文件中手动的将需要安装的包和对应的",(0,s.jsx)(n.a,{href:"https://docs.npmjs.com/about-semantic-versioning",target:"_blank",rel:"noopener noreferrer",children:"语义化版本"}),"写在 ",(0,s.jsx)(n.code,{children:'"devDependencies"'})," 里,并执行 ",(0,s.jsx)(n.code,{children:"npm install"})," 命令:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "name": "your-npm-project",\n "devDependencies": {\n "npm-package-name": "0.1.0"\n }\n}\n'})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsxs)(n.strong,{children:["在安装或者使用第三方 npm 包的时候一定要确定它们的用途,以及通过区分它们的类型确定好它们应该放在 ",(0,s.jsx)(n.code,{children:'"dependencies"'})," 还是 ",(0,s.jsx)(n.code,{children:'"devDependencies"'})," 中。"]})}),"\n",(0,s.jsxs)(n.div,{className:"rspress-directive tip",children:[(0,s.jsx)(n.div,{className:"rspress-directive-title",children:"TIP"}),(0,s.jsx)(n.div,{className:"rspress-directive-content",children:(0,s.jsxs)(n.p,{children:["一般来说,需要在源代码中使用到的包都属于 ",(0,s.jsx)(n.code,{children:"dependencies"})," 依赖。除非你通过打包的方式将依赖的代码输出到本地,那么这种情况可以将它作为 ",(0,s.jsx)(n.code,{children:"devDependencies"})," 依赖。\n"]})})]}),"\n",(0,s.jsxs)(n.h2,{id:"还需要了解的-npm-零碎知识",children:["还需要了解的 npm 零碎知识",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#还需要了解的-npm-零碎知识",children:"#"})]}),"\n",(0,s.jsxs)(n.h3,{id:"npm-包的程序入口",children:["npm 包的程序入口",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#npm-包的程序入口",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["在 ",(0,s.jsx)(n.code,{children:"package.json"})," 中存在一个 ",(0,s.jsx)(n.code,{children:'"main"'})," 属性,它对应的值是一个模块 ID,或者更直观的说是一个 NodeJS 文件路径,它是你程序的主要入口。"]}),"\n",(0,s.jsxs)(n.p,{children:["例如你的包名为 ",(0,s.jsx)(n.code,{children:"foo"}),",并且用户安装了它,然后执行 ",(0,s.jsx)(n.code,{children:'require("foo")'})," 代码,那么 ",(0,s.jsx)(n.code,{children:"foo"})," 这个 npm 包的 ",(0,s.jsx)(n.code,{children:'"main"'})," 字段对应的文件将会被导出。"]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsxs)(n.strong,{children:["推荐在你的 npm 包里一定要设置 ",(0,s.jsx)(n.code,{children:'"main"'})," 字段"]}),"。如果没有设置 ",(0,s.jsx)(n.code,{children:'"main"'}),",则默认入口为包的根目录下的 ",(0,s.jsx)(n.code,{children:"index.js"})," 文件。"]}),"\n",(0,s.jsxs)(n.p,{children:["除了需要设置 ",(0,s.jsx)(n.code,{children:'"main"'})," 属性以外,一般还会设置 ",(0,s.jsx)(n.code,{children:'"module"'})," 属性。它与 ",(0,s.jsx)(n.code,{children:'"main"'})," 属性的用途类似,它主要是用于在 webpack 场景下使用。webpack 在大多数情况下,会以 ",(0,s.jsx)(n.strong,{children:'"module" -> "main"'})," 这个顺序读取 npm 包的入口(文件)。"]}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsxs)(n.p,{children:["想要了解关于 webpack 如何做这件事,可以查看这个",(0,s.jsx)(n.a,{href:"https://webpack.js.org/configuration/resolve/#resolvemainfields",target:"_blank",rel:"noopener noreferrer",children:"链接"}),"。"]}),"\n"]}),"\n",(0,s.jsxs)(n.h3,{id:"scripts",children:['"scripts"',(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#scripts",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"package.json"})," 文件的 ",(0,s.jsx)(n.code,{children:'"scripts"'})," 属性支持一些内置的脚本和 npm 预设的生命周期事件,以及任意的脚本。"]}),"\n",(0,s.jsxs)(n.p,{children:["这些都可以通过运行 ",(0,s.jsx)(n.code,{children:"npm run-script <stage>"})," 或简称 ",(0,s.jsx)(n.code,{children:"npm run <stage>"})," 来执行。"]}),"\n",(0,s.jsxs)(n.p,{children:["名称匹配的",(0,s.jsx)(n.a,{href:"https://docs.npmjs.com/cli/v9/using-npm/scripts#pre--post-scripts",target:"_blank",rel:"noopener noreferrer",children:"前置命令和后置命令"}),"也会被运行(例如 ",(0,s.jsx)(n.code,{children:"premyscript"}),"、",(0,s.jsx)(n.code,{children:"myscript"}),"、",(0,s.jsx)(n.code,{children:"postmyscript"}),")。"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "scripts": {\n "premyscript": "",\n "myscript": "",\n "postmyscript": ""\n }\n}\n'})}),"\n",(0,s.jsxs)(n.p,{children:["当执行 ",(0,s.jsx)(n.code,{children:"npm run myscripts"})," 的时候,",(0,s.jsx)(n.code,{children:"premyscripts"})," 对应的脚本会在它之前执行,",(0,s.jsx)(n.code,{children:"postmyscripts"})," 对应的脚本会在它之后执行。"]}),"\n",(0,s.jsxs)(n.p,{children:["来自依赖的脚本命令可以用 ",(0,s.jsx)(n.code,{children:"npm explore <pkg> -- npm run <stage>"})," 运行。"]}),"\n",(0,s.jsx)(n.p,{children:"还有一些特殊的生命周期脚本(Life Scripts),只在某些情况下发生。这里介绍几个通常需要了解的情况。"}),"\n",(0,s.jsxs)(n.h4,{id:"npm-install",children:[(0,s.jsx)(n.code,{children:"npm install"}),(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#npm-install",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["当你运行 ",(0,s.jsx)(n.code,{children:"npm install -g <pkg-name>"})," 时,以下脚本会运行。"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"preinstall"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"install"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"postinstall"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"prepublish"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"preprepare"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"prepare"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"postprepare"})}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["如果你的软件包根目录有一个 ",(0,s.jsx)(n.code,{children:"binding.gyp"})," 文件,而你没有定义 ",(0,s.jsx)(n.code,{children:"install"})," 或 ",(0,s.jsx)(n.code,{children:"preinstall"})," 脚本,那么 npm 将以 ",(0,s.jsx)(n.code,{children:"node-gyp rebuild"})," 作为默认的 install 命令,使用 ",(0,s.jsx)(n.a,{href:"https://github.com/nodejs/node-gyp",target:"_blank",rel:"noopener noreferrer",children:"node-gyp"})," 进行编译。"]}),"\n",(0,s.jsxs)(n.h4,{id:"npm-publish",children:[(0,s.jsx)(n.code,{children:"npm publish"}),(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#npm-publish",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"当发布项目的时候,执行该命令会触发以下脚本:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"prepublishOnly"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"prepack"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"prepare"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"postpack"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"publish"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"postpublish"})}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["当以 ",(0,s.jsx)(n.a,{href:"https://docs.npmjs.com/cli/v7/commands/npm-publish#dry-run",target:"_blank",rel:"noopener noreferrer",children:(0,s.jsx)(n.code,{children:"--dry-run"})})," 模式运行的时候,",(0,s.jsx)(n.code,{children:"prepare"})," 对应的脚本将不会执行。"]}),"\n",(0,s.jsxs)(n.h3,{id:"peerdependencies",children:["peerDependencies",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#peerdependencies",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"在某些情况下,你的 npm 项目与它的宿主工具或者库之间存在某种兼容关系(例如一个 webpack 插件项目和 webpack),同时你的 npm 项目不想将宿主作为必要的依赖,这个时候通常说明你的项目可能是这个宿主工具或者库的插件。你的 npm 项目会对宿主包的版本有一定的要求,因为只有在特定的版本下才会暴露出 npm 项目所需要的 API。"}),"\n",(0,s.jsxs)(n.p,{children:["关于更多 ",(0,s.jsx)(n.code,{children:"peerDependencies"})," 的解释,可以通过下面的链接了解 npm、pnpm、Yarn 对于它的不同处理方式:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://docs.npmjs.com/cli/v9/configuring-npm/package-json#peerdependencies",target:"_blank",rel:"noopener noreferrer",children:"npm 对 peerDependencies 的解释"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://pnpm.io/feature-comparison",target:"_blank",rel:"noopener noreferrer",children:"pnpm vs npm VS Yarn"})}),"\n"]}),"\n",(0,s.jsxs)(n.h2,{id:"npm-包管理器",children:["npm 包管理器",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#npm-包管理器",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["除了 npm 这种标准的包管理器以外,目前主流的还有 ",(0,s.jsx)(n.strong,{children:"pnpm"})," 和 ",(0,s.jsx)(n.strong,{children:"Yarn"}),",它们都是不错的 npm cli 替代品。"]}),"\n",(0,s.jsxs)(n.p,{children:["推荐使用 ",(0,s.jsx)(n.a,{href:"https://pnpm.io/installation",target:"_blank",rel:"noopener noreferrer",children:"pnpm"})," 来管理项目依赖,可以通过下面的方式安装它:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"npm install -g pnpm\n"})}),"\n",(0,s.jsxs)(n.h2,{id:"modernjs-module-配置文件",children:["Modern.js Module 配置文件",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#modernjs-module-配置文件",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["通过 ",(0,s.jsx)(n.code,{children:"@modern-js/create"})," 创建的项目目录下提供了 Modern.js Module 的配置文件 —— ",(0,s.jsx)(n.code,{children:"modern.config.(j|t)s"}),"。但 ",(0,s.jsx)(n.code,{children:"modern.config"})," 配置文件不是必须存在的。"]}),"\n",(0,s.jsx)(n.p,{children:"默认情况下,生成的配置文件的内容如下:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",meta:'title="modern.config.ts"',children:"import { moduleTools, defineConfig } from '@modern-js/module-tools';\n\nexport default defineConfig({\n plugins: [moduleTools()],\n buildPreset: 'npm-library',\n});\n"})}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsxs)(n.strong,{children:["我们推荐使用 ",(0,s.jsx)(n.code,{children:"defineConfig"})," 函数"]}),",不过并不强制使用它。因此你也可以在配置文件中直接返回一个对象:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",meta:'title="modern.config.ts"',children:"import { moduleTools } from '@modern-js/module-tools';\n\nexport default {\n plugins: [moduleTools()],\n buildPreset: 'npm-library',\n};\n"})})]})}function c(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,d.ah)(),e.components);return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(i,{...e})}):i(e)}let l=c;c.__RSPRESS_PAGE_META={},c.__RSPRESS_PAGE_META["zh%2Fguide%2Fbasic%2Fbefore-getting-started.md"]={toc:[{text:"环境准备",id:"环境准备",depth:2},{text:"初识 npm",id:"初识-npm",depth:2},{text:"npm 包类型项目",id:"npm-包类型项目",depth:2},{text:"使用第三方 npm 包",id:"使用第三方-npm-包",depth:2},{text:"还需要了解的 npm 零碎知识",id:"还需要了解的-npm-零碎知识",depth:2},{text:"npm 包的程序入口",id:"npm-包的程序入口",depth:3},{text:'"scripts"',id:"scripts",depth:3},{text:"`npm install`",id:"npm-install",depth:4},{text:"`npm publish`",id:"npm-publish",depth:4},{text:"peerDependencies",id:"peerdependencies",depth:3},{text:"npm 包管理器",id:"npm-包管理器",depth:2},{text:"Modern.js Module 配置文件",id:"modernjs-module-配置文件",depth:2}],title:"开始之前",frontmatter:{sidebar_position:1}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_modern_js_module_tools_docs=self.webpackChunk_modern_js_module_tools_docs||[]).push([["8451"],{8565:function(e,o,n){n.r(o),n.d(o,{default:function(){return i}});var r=n(8093),t=n(5878);function s(e){let o=Object.assign({h1:"h1",a:"a",p:"p",ul:"ul",li:"li",strong:"strong",code:"code"},(0,t.ah)(),e.components);return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(o.h1,{id:"welcome-to-modernjs-module",children:["Welcome to Modern.js Module",(0,r.jsx)(o.a,{className:"header-anchor","aria-hidden":"true",href:"#welcome-to-modernjs-module",children:"#"})]}),"\n",(0,r.jsx)(o.p,{children:"Modern.js Module is a modules engineering solution for Modern.js, as well as a core dependency. It allows developers to build, debug, and publish module type project more easily. A module type project can mostly be thought of as an npm package type project, which may be a component, component library or tool library project."}),"\n",(0,r.jsx)(o.p,{children:"If you are planning to develop a project of the npm package type, then you came to the right place! Modern.js provides a professional Modern.js Module. It gives you:"}),"\n",(0,r.jsxs)(o.ul,{children:["\n",(0,r.jsxs)(o.li,{children:[(0,r.jsx)(o.strong,{children:"Simple project initialization"}),": simply execute the ",(0,r.jsx)(o.code,{children:"npx @modern-js/create project-dir"})," command, followed by a few interactive questions, to create a complete module type project. The created project also supports the choice of two package managers, ",(0,r.jsx)(o.a,{href:"https://pnpm.io/",target:"_blank",rel:"noopener noreferrer",children:(0,r.jsx)(o.strong,{children:"pnpm"})})," and ",(0,r.jsx)(o.a,{href:"https://classic.yarnpkg.com/",target:"_blank",rel:"noopener noreferrer",children:(0,r.jsx)(o.strong,{children:"Yarn"})}),"."]}),"\n",(0,r.jsxs)(o.li,{children:[(0,r.jsx)(o.strong,{children:"Comprehensive build capabilities and faster builds"}),": Modern.js Module provides high-performance build capabilities based on ",(0,r.jsx)(o.a,{href:"https://esbuild.github.io/getting-started/",target:"_blank",rel:"noopener noreferrer",children:"esbuild"})," and ",(0,r.jsx)(o.a,{href:"https://swc.rs/",target:"_blank",rel:"noopener noreferrer",children:"SWC"}),", and provides rich configurations for different build scenarios."]}),"\n",(0,r.jsxs)(o.li,{children:[(0,r.jsx)(o.strong,{children:"Storybook debugging tools"}),": Modern.js Module provides ",(0,r.jsx)(o.a,{href:"https://storybook.js.org/",target:"_blank",rel:"noopener noreferrer",children:"Storybook"})," debugging tools for debugging module projects. After installing the Storybook plugin for Modern.js Module, you can start it with the ",(0,r.jsx)(o.code,{children:"storybook dev"})," command. You can use Storybook not only for debugging components, but also for other types of modules."]}),"\n",(0,r.jsxs)(o.li,{children:[(0,r.jsx)(o.strong,{children:"Versioning based on Changesets"}),": When you need to record changes to a project, you can use the ",(0,r.jsx)(o.code,{children:"modern change"})," command to generate a Markdown file containing the changes; when you need to upgrade a project, you can use the ",(0,r.jsx)(o.code,{children:"modern bump"})," command to analyze and upgrade the version through the Markdown file; when you need to release a project, you can use the ",(0,r.jsx)(o.code,{children:"modern release"})," command to release the project; Modern.js Module implements these commands based on ",(0,r.jsx)(o.a,{href:"https://github.com/changesets/changesets",target:"_blank",rel:"noopener noreferrer",children:"Changesets"}),"."]}),"\n",(0,r.jsxs)(o.li,{children:[(0,r.jsx)(o.strong,{children:"Extensible plugin mechanism"}),": Want to integrate additional debugging tools for your project? Or maybe you want to do some extra processing during the build process, Modern.js Module provides a plugin mechanism and plugin hooks that cover both the ",(0,r.jsx)(o.code,{children:"dev"})," command and the ",(0,r.jsx)(o.code,{children:"build"})," command process. You can use them to extend the capabilities of your project."]}),"\n",(0,r.jsxs)(o.li,{children:[(0,r.jsx)(o.strong,{children:"Lots more!"})," Modern.js Module will continue to optimize its build and debug features in the future. If there are important issues to be solved in module project building, or if a mainstream module project debugging tool or pattern emerges, then they will probably be supported by Modern.js Module."]}),"\n"]})]})}function d(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:o}=Object.assign({},(0,t.ah)(),e.components);return o?(0,r.jsx)(o,{...e,children:(0,r.jsx)(s,{...e})}):s(e)}let i=d;d.__RSPRESS_PAGE_META={},d.__RSPRESS_PAGE_META["en%2Fguide%2Fintro%2Fwelcome.md"]={toc:[],title:"Welcome to Modern.js Module",frontmatter:{sidebar_position:1}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_modern_js_module_tools_docs=self.webpackChunk_modern_js_module_tools_docs||[]).push([["8689"],{86:function(e,n,t){t.r(n),t.d(n,{default:function(){return l}});var i=t(8093),s=t(5878);function o(e){let n=Object.assign({pre:"pre",code:"code",p:"p"},(0,s.ah)(),e.components);return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-js",meta:'title="modern.config.ts"',children:"import { myEsbuildPlugin } from './myEsbuildPlugin';\n\nexport default defineConfig({\n buildConfig: {\n esbuildOptions: options => {\n options.plugins = [myEsbuildPlugin, ...options.plugins];\n return options;\n },\n },\n});\n"})}),"\n",(0,i.jsx)(n.p,{children:"When adding an esbuild plugin, please note that you need to add the plugin at the beginning of the plugins array. This is because the Modern.js Module is also integrated into the entire build process through an esbuild plugin. Therefore, custom plugins need to be registered with higher priority."})]})}function r(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,s.ah)(),e.components);return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(o,{...e})}):o(e)}let l=r;r.__RSPRESS_PAGE_META={},r.__RSPRESS_PAGE_META["en%2Fcomponents%2Fregister-esbuild-plugin.mdx"]={toc:[],title:"",frontmatter:{}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_modern_js_module_tools_docs=self.webpackChunk_modern_js_module_tools_docs||[]).push([["8694"],{2927:function(e,l,n){n.r(l),n.d(l,{default:function(){return t}});var s=n(8093),o=n(5878),i=n(8078);function r(e){let l=Object.assign({h1:"h1",a:"a",div:"div",p:"p",code:"code",h2:"h2",h3:"h3",pre:"pre",ul:"ul",li:"li",strong:"strong"},(0,o.ah)(),e.components);return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(l.h1,{id:"polyfill-插件",children:["Polyfill 插件",(0,s.jsx)(l.a,{className:"header-anchor","aria-hidden":"true",href:"#polyfill-插件",children:"#"})]}),"\n",(0,s.jsxs)(l.div,{className:"rspress-directive tip",children:[(0,s.jsx)(l.div,{className:"rspress-directive-title",children:"TIP"}),(0,s.jsxs)(l.div,{className:"rspress-directive-content",children:[(0,s.jsx)(l.p,{children:"通常情况下,我们不需要为 npm 包注入 polyfill,这一步应该在 Web 应用的框架侧完成,但是在某些场景,为了让我们的库能够直接运行在低版本浏览器里,我们需要注入 polyfill。"}),"\n",(0,s.jsxs)(l.p,{children:["请注意,此插件并不会转化你的代码语法,只会为你的代码中使用到的不支持的功能注入 polyfill,把它们作为普通函数导入而不是污染全局。你需要安装 ",(0,s.jsx)(l.code,{children:"core-js-pure"})," 依赖"]}),"\n"]})]}),"\n",(0,s.jsxs)(l.h2,{id:"快速开始",children:["快速开始",(0,s.jsx)(l.a,{className:"header-anchor","aria-hidden":"true",href:"#快速开始",children:"#"})]}),"\n",(0,s.jsxs)(l.h3,{id:"安装",children:["安装",(0,s.jsx)(l.a,{className:"header-anchor","aria-hidden":"true",href:"#安装",children:"#"})]}),"\n","\n",(0,s.jsx)(i.SU,{command:"add @modern-js/plugin-module-polyfill -D"}),"\n",(0,s.jsxs)(l.h3,{id:"注册插件",children:["注册插件",(0,s.jsx)(l.a,{className:"header-anchor","aria-hidden":"true",href:"#注册插件",children:"#"})]}),"\n",(0,s.jsx)(l.p,{children:"在 Modern.js Module 中,你可以按照如下方式注册插件:"}),"\n",(0,s.jsx)(l.pre,{children:(0,s.jsx)(l.code,{className:"language-ts",children:"import { moduleTools, defineConfig } from '@modern-js/module-tools';\nimport { modulePluginPolyfill } from '@modern-js/plugin-module-polyfill';\n\nexport default defineConfig({\n plugins: [moduleTools(), modulePluginPolyfill()],\n});\n"})}),"\n",(0,s.jsx)(l.p,{children:"你也可以通过 hooks 配置注册,例如你同时具有多份构建配置,并只需要在 bundle 构建时注入 polyfill:"}),"\n",(0,s.jsx)(l.pre,{children:(0,s.jsx)(l.code,{className:"language-ts",children:"import { moduleTools, defineConfig } from '@modern-js/module-tools';\nimport { getPolyfillHook } from '@modern-js/plugin-module-polyfill';\n\nconst polyfillHook = getPolyfillHook();\n\nexport default defineConfig({\n plugins: [moduleTools()],\n buildConfig: [\n {\n buildType: 'bundle',\n hooks: [polyfillHook],\n },\n {\n buildType: 'bundleless',\n },\n ],\n});\n"})}),"\n",(0,s.jsxs)(l.h2,{id:"配置",children:["配置",(0,s.jsx)(l.a,{className:"header-anchor","aria-hidden":"true",href:"#配置",children:"#"})]}),"\n",(0,s.jsxs)(l.ul,{children:["\n",(0,s.jsx)(l.li,{children:(0,s.jsx)(l.strong,{children:"类型:"})}),"\n"]}),"\n",(0,s.jsx)(l.pre,{children:(0,s.jsx)(l.code,{className:"language-ts",children:"type options = {\n targets?: Record<string, string> | string;\n};\n"})}),"\n",(0,s.jsxs)(l.h3,{id:"targets",children:["targets",(0,s.jsx)(l.a,{className:"header-anchor","aria-hidden":"true",href:"#targets",children:"#"})]}),"\n",(0,s.jsxs)(l.p,{children:["参考 ",(0,s.jsx)(l.a,{href:"https://babeljs.io/docs/options#targets",target:"_blank",rel:"noopener noreferrer",children:"Babel target"}),"."]}),"\n",(0,s.jsx)(l.p,{children:"下面是一个例子:"}),"\n",(0,s.jsx)(l.pre,{children:(0,s.jsx)(l.code,{className:"language-ts",children:"import { moduleTools, defineConfig } from '@modern-js/module-tools';\nimport { modulePluginPolyfill } from '@modern-js/plugin-module-polyfill';\n\nexport default defineConfig({\n plugins: [\n moduleTools(),\n modulePluginPolyfill({\n targets: '> 0.25%, not dead',\n }),\n ],\n});\n"})})]})}function d(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:l}=Object.assign({},(0,o.ah)(),e.components);return l?(0,s.jsx)(l,{...e,children:(0,s.jsx)(r,{...e})}):r(e)}let t=d;d.__RSPRESS_PAGE_META={},d.__RSPRESS_PAGE_META["zh%2Fplugins%2Fofficial-list%2Fplugin-polyfill.mdx"]={toc:[{text:"快速开始",id:"快速开始",depth:2},{text:"安装",id:"安装",depth:3},{text:"注册插件",id:"注册插件",depth:3},{text:"配置",id:"配置",depth:2},{text:"targets",id:"targets",depth:3}],title:"Polyfill 插件",frontmatter:{}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_modern_js_module_tools_docs=self.webpackChunk_modern_js_module_tools_docs||[]).push([["8713"],{2302:function(e,n,r){r.r(n),r.d(n,{default:function(){return t}});var s=r(8093),o=r(5878),l=r(8078);function i(e){let n=Object.assign({h1:"h1",a:"a",p:"p",div:"div",code:"code",h2:"h2",h3:"h3",pre:"pre",ul:"ul",li:"li",strong:"strong"},(0,o.ah)(),e.components);return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.h1,{id:"import-插件",children:["Import 插件",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#import-插件",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["提供与 ",(0,s.jsx)(n.a,{href:"https://github.com/umijs/babel-plugin-import",target:"_blank",rel:"noopener noreferrer",children:"babel-plugin-import"})," 等价的能力和配置,基于 ",(0,s.jsx)(n.a,{href:"https://swc.rs/",target:"_blank",rel:"noopener noreferrer",children:"SWC"})," 实现。"]}),"\n",(0,s.jsxs)(n.div,{className:"rspress-directive tip",children:[(0,s.jsx)(n.div,{className:"rspress-directive-title",children:"TIP"}),(0,s.jsx)(n.div,{className:"rspress-directive-content",children:(0,s.jsxs)(n.p,{children:["从 ",(0,s.jsx)(n.code,{children:"@modern-js/module-tools"})," 2.16.0 版本开始,该插件功能内置在 Modern.js Module 中,由 ",(0,s.jsx)(n.a,{href:"/api/config/build-config.html#transformimport",children:(0,s.jsx)(n.code,{children:"transformImport"})}),"\n配置提供。\n"]})})]}),"\n",(0,s.jsxs)(n.h2,{id:"快速开始",children:["快速开始",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#快速开始",children:"#"})]}),"\n",(0,s.jsxs)(n.h3,{id:"安装",children:["安装",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#安装",children:"#"})]}),"\n","\n",(0,s.jsx)(l.SU,{command:"add @modern-js/plugin-module-import -D"}),"\n",(0,s.jsxs)(n.h3,{id:"注册插件",children:["注册插件",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#注册插件",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"在 Modern.js Module 中,你可以按照如下方式注册插件:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"import { moduleTools, defineConfig } from '@modern-js/module-tools';\nimport { modulePluginImport } from '@modern-js/plugin-module-import';\n\nexport default defineConfig({\n plugins: [\n moduleTools(),\n modulePluginImport({\n pluginImport: [\n {\n libraryName: 'antd',\n style: true,\n },\n ],\n }),\n ],\n});\n"})}),"\n",(0,s.jsx)(n.p,{children:"这样我们就可以在 Modern.js Module 中使用自动导入的能力了。"}),"\n",(0,s.jsxs)(n.h2,{id:"配置",children:["配置",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#配置",children:"#"})]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.strong,{children:"类型:"})}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"type Options = {\n pluginImport?: ImportItem[];\n};\n"})}),"\n",(0,s.jsxs)(n.h3,{id:"pluginimport",children:["pluginImport",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#pluginimport",children:"#"})]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["类型:",(0,s.jsx)(n.code,{children:"object[]"})]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["其中数组元素为一个 babel-plugin-import 的配置对象。配置对象可以参考 ",(0,s.jsx)(n.a,{href:"https://github.com/umijs/babel-plugin-import#options",target:"_blank",rel:"noopener noreferrer",children:"options"}),"。"]}),"\n",(0,s.jsx)(n.p,{children:"使用示例:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"import { modulePluginImport } from '@modern-js/plugin-module-import';\nimport { moduleTools, defineConfig } from '@modern-js/module-tools';\n\nexport default defineConfig({\n plugins: [\n moduleTools(),\n modulePluginImport({\n pluginImport: [\n // babel-plugin-import 的 options 配置\n {\n libraryName: 'foo',\n style: true,\n },\n ],\n }),\n ],\n});\n"})}),"\n",(0,s.jsxs)(n.h2,{id:"注意事项",children:["注意事项",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#注意事项",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.a,{href:"https://swc.rs/",target:"_blank",rel:"noopener noreferrer",children:"SWC"})," (Speedy Web Compiler) 是基于 Rust 语言编写的,而该插件是基于 SWC,移植自 ",(0,s.jsx)(n.a,{href:"https://github.com/umijs/babel-plugin-import",target:"_blank",rel:"noopener noreferrer",children:"babel-plugin-import"}),",配置选项保持了一致。"]}),"\n",(0,s.jsxs)(n.p,{children:["一些配置可以传入函数,例如 ",(0,s.jsx)(n.code,{children:"customName"}),",",(0,s.jsx)(n.code,{children:"customStyleName"})," 等, 但在 Modern.js Module 里,我们不建议在此配置项里使用函数。\n因为我们会在 esbuild 的插件里调用 SWC,然后再当 Rust 通过 Node-API 调用这些配置函数时,会出现死锁现象。"]}),"\n",(0,s.jsxs)(n.p,{children:["简单的函数逻辑其实可以通过模版语言来代替,下面是一个 ",(0,s.jsx)(n.code,{children:"customName"})," 使用模板的示例:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"import { MyButton as Btn } from 'foo';\n"})}),"\n",(0,s.jsx)(n.p,{children:"添加以下配置:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"modulePluginImport({\n pluginImport: [\n {\n libraryName: 'foo',\n customName: 'foo/es/{{ member }}',\n },\n ],\n});\n"})}),"\n",(0,s.jsxs)(n.p,{children:["其中的 ",(0,s.jsx)(n.code,{children:"{{ member }}"})," 会被替换为相应的引入成员,转换后:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"import Btn from 'foo/es/MyButton';\n"})}),"\n",(0,s.jsxs)(n.p,{children:["可以看出配置 ",(0,s.jsx)(n.code,{children:'customName: "foo/es/{{ member }}"'})," 的效果等同于配置 ",(0,s.jsx)(n.code,{children:" customName: (member) => `foo/es/${member}` "})," 。"]}),"\n",(0,s.jsxs)(n.p,{children:["这里使用到的模版是 ",(0,s.jsx)(n.a,{href:"https://handlebarsjs.com",target:"_blank",rel:"noopener noreferrer",children:"handlebars"}),",模版配置中还内置了一些有用的辅助工具,还是以上面的导入语句为例,配置成:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"import { modulePluginImport } from '@modern-js/plugin-module-import';\nimport { moduleTools, defineConfig } from '@modern-js/module-tools';\n\nexport default defineConfig({\n plugins: [\n moduleTools(),\n modulePluginImport({\n pluginImport: [\n {\n libraryName: 'foo',\n customName: 'foo/es/{{ kebabCase member }}',\n },\n ],\n }),\n ],\n});\n"})}),"\n",(0,s.jsx)(n.p,{children:"会转换成下面的结果:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"import Btn from 'foo/es/my-button';\n"})}),"\n",(0,s.jsxs)(n.p,{children:["除了 ",(0,s.jsx)(n.code,{children:"kebabCase"})," 以外还有 ",(0,s.jsx)(n.code,{children:"camelCase"}),",",(0,s.jsx)(n.code,{children:"snakeCase"}),",",(0,s.jsx)(n.code,{children:"upperCase"}),",",(0,s.jsx)(n.code,{children:"lowerCase"})," 可以使用。"]})]})}function d(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,o.ah)(),e.components);return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(i,{...e})}):i(e)}let t=d;d.__RSPRESS_PAGE_META={},d.__RSPRESS_PAGE_META["zh%2Fplugins%2Fofficial-list%2Fplugin-import.mdx"]={toc:[{text:"快速开始",id:"快速开始",depth:2},{text:"安装",id:"安装",depth:3},{text:"注册插件",id:"注册插件",depth:3},{text:"配置",id:"配置",depth:2},{text:"pluginImport",id:"pluginimport",depth:3},{text:"注意事项",id:"注意事项",depth:2}],title:"Import 插件",frontmatter:{}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_modern_js_module_tools_docs=self.webpackChunk_modern_js_module_tools_docs||[]).push([["8750"],{7499:function(e,n,i){i.r(n),i.d(n,{default:function(){return d}});var r=i(8093),s=i(5878);function o(e){let n=Object.assign({h1:"h1",a:"a",p:"p",strong:"strong",h2:"h2",h3:"h3",code:"code",pre:"pre",ul:"ul",li:"li",ol:"ol",h4:"h4",img:"img"},(0,s.ah)(),e.components);return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.h1,{id:"build-faq",children:["Build FAQ",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#build-faq",children:"#"})]}),"\n",(0,r.jsx)(n.p,{children:"Here only some common problems and bad cases are recorded."}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.strong,{children:["If the build products do not meet expectations, especially when ",(0,r.jsx)(n.a,{href:"/api/config/build-preset",children:"buildPreset"})," is configured,\nplease first understand what configuration items buildPreset represents, and then check each configuration item based on all configuration items."]})}),"\n",(0,r.jsxs)(n.h2,{id:"product-faq",children:["Product FAQ",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#product-faq",children:"#"})]}),"\n",(0,r.jsxs)(n.h3,{id:"initialization-of-class-fields",children:["Initialization of Class Fields",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#initialization-of-class-fields",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["TypeSript provides the ",(0,r.jsx)(n.code,{children:"useDefineForClassFields"})," configuration to control the conversion handling for ",(0,r.jsx)(n.code,{children:"public class fields"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"If we have a piece of code:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"class C {\n foo = 100;\n bar: string;\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["When ",(0,r.jsx)(n.code,{children:"useDefineForClassFields"})," is ",(0,r.jsx)(n.code,{children:"false"}),", then the compiled code will look like:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"class C {\n constructor() {\n this.foo = 100;\n }\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["When ",(0,r.jsx)(n.code,{children:"useDefineForClassFields"})," is ",(0,r.jsx)(n.code,{children:"true"}),", then the compiled code will look like:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"class C {\n constructor() {\n Object.defineProperty(this, 'foo', {\n enumerable: true,\n configurable: true,\n writable: true,\n value: 100,\n });\n Object.defineProperty(this, 'bar', {\n enumerable: true,\n configurable: true,\n writable: true,\n value: void 0,\n });\n }\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Also the default value of this configuration will change depending on the ",(0,r.jsx)(n.a,{href:"https://www.typescriptlang.org/tsconfig#target",target:"_blank",rel:"noopener noreferrer",children:(0,r.jsx)(n.code,{children:"target"})})," configuration of tsconfig.json: When ",(0,r.jsx)(n.code,{children:"target"})," is ES2022 or higher, then ",(0,r.jsx)(n.code,{children:"useDefineForClassFields"})," is configured to ",(0,r.jsx)(n.code,{children:"true"})," by default, otherwise it defaults to ",(0,r.jsx)(n.code,{children:"false"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"For more information on this configuration of TypeScript, you can refer to the following link:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#the-usedefineforclassfields-flag-and-the-declare-property-modifier",target:"_blank",rel:"noopener noreferrer",children:"The useDefineForClassFields Flag and The declare Property Modifier"})}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"The Modern.js Module will currently process according to the following logic:"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["The first decision to enable this feature inside Modern.js Module is based on the ",(0,r.jsx)(n.code,{children:"useDefineForClassFields"})," configuration in tsconfig.json of the current project. Currently, only the contents of the tsconfig.json file under the current project path will be read, and the final tsconfig configuration based on the ",(0,r.jsx)(n.a,{href:"https://www.typescriptlang.org/tsconfig#extends",target:"_blank",rel:"noopener noreferrer",children:(0,r.jsx)(n.code,{children:"extends"})})," configuration is not supported at this time."]}),"\n",(0,r.jsxs)(n.li,{children:["If the ",(0,r.jsx)(n.code,{children:"useDefineForClassFields"})," configuration of tsconfig.json is not detected, the default value is determined based on the ",(0,r.jsx)(n.code,{children:"target"})," configuration of tsconfig.json. If ",(0,r.jsx)(n.code,{children:"target"})," is greater than ",(0,r.jsx)(n.code,{children:"ES2022"})," (including ",(0,r.jsx)(n.code,{children:"EsNext"}),"), then ",(0,r.jsx)(n.code,{children:"useDefineForClassFields"})," defaults to ",(0,r.jsx)(n.code,{children:"true"}),", otherwise it is ",(0,r.jsx)(n.code,{children:"false"}),"."]}),"\n",(0,r.jsxs)(n.li,{children:["If the ",(0,r.jsx)(n.code,{children:"target"})," of tsconfig.json is not detected, it is processed according to the value of ",(0,r.jsx)(n.code,{children:"useDefineForClassFields"})," as ",(0,r.jsx)(n.code,{children:"true"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.h3,{id:"babel-plugin-lodash-treats-the-introduced-lodash-as-undefined",children:["babel-plugin-lodash treats the introduced lodash as ",(0,r.jsx)(n.code,{children:"undefined"}),(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#babel-plugin-lodash-treats-the-introduced-lodash-as-undefined",children:"#"})]}),"\n",(0,r.jsx)(n.p,{children:"This problem occurs when using something like the following:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"import * as Lodash from 'lodash';\n\nexport const libs = {\n _: Lodash,\n};\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Current related issues on the ",(0,r.jsx)(n.code,{children:"babel-plugin-lodash"})," Github:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://github.com/lodash/babel-plugin-lodash/issues/235",target:"_blank",rel:"noopener noreferrer",children:"#235"})}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["The solution to this problem is to remove ",(0,r.jsx)(n.code,{children:"babel-plugin-lodash"}),", since the plugin is not needed for on-demand referencing at this point and using it would have side effects."]}),"\n",(0,r.jsxs)(n.p,{children:["A similar situation occurs with ",(0,r.jsx)(n.code,{children:"babel-plugin-import"}),". If there is code like the following:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"import * as Comps from 'components';\n\nexport const libs = {\n comps: Comps,\n};\n"})}),"\n",(0,r.jsxs)(n.p,{children:["In this case ",(0,r.jsx)(n.code,{children:"babel-plugin-import"})," may also cause ",(0,r.jsx)(n.code,{children:"Comps"})," to become ",(0,r.jsx)(n.code,{children:"undefined"}),". So you need to remove the corresponding ",(0,r.jsx)(n.code,{children:"babel-plugin-import"})," as well."]}),"\n",(0,r.jsxs)(n.h3,{id:"cannot-find-module-http",children:["Cannot find module 'http'",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#cannot-find-module-http",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["If the output reports an error like ",(0,r.jsx)(n.code,{children:"Cannot find module 'http'"})," at browser runtime, it means that your output has bundled node modules.\nThis may occur if some of your dependencies support both browser and node, such as ",(0,r.jsx)(n.code,{children:"axios"}),", in which case you only need to set the ",(0,r.jsx)(n.a,{href:"/api/config/build-config.html#platform",children:"platform"})," to ",(0,r.jsx)(n.code,{children:"browser"}),".\nIf some third-party packages don't support the browser, you may need to manually inject ",(0,r.jsx)(n.a,{href:"/plugins/official-list/plugin-node-polyfill",children:"node polyfill"}),"."]}),"\n",(0,r.jsxs)(n.h2,{id:"exceptions-faq",children:["Exceptions FAQ",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#exceptions-faq",children:"#"})]}),"\n",(0,r.jsxs)(n.h3,{id:"dynamic-require-of-react-is-not-supported",children:['Dynamic require of "react" is not supported',(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#dynamic-require-of-react-is-not-supported",children:"#"})]}),"\n",(0,r.jsxs)(n.h4,{id:"problem-description",children:["Problem Description",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#problem-description",children:"#"})]}),"\n",(0,r.jsx)(n.p,{children:"When the product format in the product configuration of the build is ES modules."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"export default defineConfig({\n buildConfig: {\n format: 'esm',\n },\n});\n"})}),"\n",(0,r.jsx)(n.p,{children:"If you import a cjs product from a third-party npm package, the resulting product may not work properly under webpack."}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{src:"https://lf3-static.bytednsdoc.com/obj/eden-cn/shylnyhaeh7uldvivhn/1280X1280.png",alt:""})}),"\n",(0,r.jsxs)(n.h4,{id:"solution",children:["Solution",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#solution",children:"#"})]}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"First you need to find which third-party package is causing the problem"}),". For example, if the error message points to the ",(0,r.jsx)(n.code,{children:"react"})," package, then look for a third-party package that has code like ",(0,r.jsx)(n.code,{children:"require('react')"})," in it. For example ",(0,r.jsx)(n.a,{href:"https://www.npmjs.com/package/react-draggable",target:"_blank",rel:"noopener noreferrer",children:(0,r.jsx)(n.code,{children:"react-draggable"})}),", which only contains ",(0,r.jsx)(n.code,{children:"cjs"})," artifacts, then the problem is localized to the ",(0,r.jsx)(n.code,{children:"react-draggable"})," package."]}),"\n",(0,r.jsxs)(n.li,{children:["Then we need to exclude this package with the following configuration, i.e. ",(0,r.jsx)(n.strong,{children:"not package problematic third-party packages"}),"."]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"export default defineConfig({\n buildConfig: {\n externals: ['react-draggable'],\n },\n});\n"})}),"\n",(0,r.jsxs)(n.h4,{id:"reference-links",children:["Reference Links",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#reference-links",children:"#"})]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://stackoverflow.com/questions/68423950/when-using-esbuild-with-external-react-i-get-dynamic-require-of-react-is-not-s",target:"_blank",rel:"noopener noreferrer",children:'When using esbuild with external react I get Dynamic require of "react" is not supported'})}),"\n"]}),"\n",(0,r.jsxs)(n.h3,{id:"during-compilation-an-error-was-reported-in-the-less-file-of-a-component-libraryoperation-on-an-invalid-type",children:["During compilation, an error was reported in the less file of a component library:",(0,r.jsx)(n.code,{children:"'Operation on an invalid type'"}),(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#during-compilation-an-error-was-reported-in-the-less-file-of-a-component-libraryoperation-on-an-invalid-type",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["This is probably because the component library depends on Less version v3, while Modern.js Module defaults to v4. v3 and v4 have a Break Change in the ",(0,r.jsx)(n.code,{children:"math"})," configuration, check this ",(0,r.jsx)(n.a,{href:"https://stackoverflow.com/questions/73298187/less-error-operation-on-an-invalid-type-in-antd-dependency",target:"_blank",rel:"noopener noreferrer",children:"link"})," for details."]}),"\n",(0,r.jsx)(n.p,{children:"Therefore, if a component library like this is used in the source code:"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"buildPreset"})," is used in the build configuration, make the following changes:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:"module.exports = {\n buildPreset({ extendPreset }) {\n return extendPreset('your-build-preset', {\n style: {\n less: {\n lessOptions: {\n math: 'always',\n },\n },\n },\n });\n },\n};\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Or, if a custom ",(0,r.jsx)(n.code,{children:"buildConfig"})," is used, modify it as follows:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:"module.exports = {\n buildConfig: {\n style: {\n less: {\n lessOptions: {\n math: 'always',\n },\n },\n },\n },\n};\n"})}),"\n",(0,r.jsx)(n.p,{children:"If you are using a component like this in Storybook, you will need to modify the debugging configuration of Storybook:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",meta:"filename='.storybook/main.ts'",children:"module.exports = {\n framework: {\n options: {\n builderConfig: {\n tools: {\n webpackChain(chain, { CHAIN_ID }) {\n chain.module\n .rule(CHAIN_ID.RULE.LESS)\n .use(CHAIN_ID.USE.LESS)\n .tap(options => {\n options.lessOptions = {\n ...options.lessOptions,\n math: 'always',\n };\n return options;\n });\n },\n },\n },\n },\n },\n};\n"})}),"\n",(0,r.jsxs)(n.h3,{id:"bundleless-dts-failed",children:["Bundleless DTS failed",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#bundleless-dts-failed",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["In the bundleless scenario, it's ",(0,r.jsx)(n.code,{children:"tsc"})," that generates the type declaration file directly. You can find the problem file by printing the error message in the terminal.\nFor source code files, it is recommended to fix the type problem, which can better enable reuse of your package. However. if you encounter a type checking problem with a thrid-party package:"]}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["enable ",(0,r.jsx)(n.a,{href:"https://www.typescriptlang.org/tsconfig#skipLibCheck",target:"_blank",rel:"noopener noreferrer",children:"skipLibCheck"})," to skip the d.ts check of the thrid-party package."]}),"\n",(0,r.jsxs)(n.li,{children:["If the package exports ts files directly, skipLibCheck will not work because it can only skip the d.ts check,\nso you can only turn off ",(0,r.jsx)(n.a,{href:"/api/config/build-config.html#dtsabortonerror",children:"dts.abortOnError"})," to ignore these errors."]}),"\n"]}),"\n",(0,r.jsxs)(n.h3,{id:"bundle-dts-failed",children:["Bundle DTS failed",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#bundle-dts-failed",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["The Modern.js Module directly uses ",(0,r.jsx)(n.a,{href:"https://github.com/Swatinem/rollup-plugin-dts",target:"_blank",rel:"noopener noreferrer",children:"rollup-plugin-dts"})," to package your type description files.\n",(0,r.jsx)(n.strong,{children:"It may not be able to handle the type files of some third-party dependencies"})]}),"\n",(0,r.jsxs)(n.p,{children:['If you encounter an error message titled "Bundle DTS failed" during the build process of the Modern.js Module, you can observe that the error message is from a third-party dependency.\nTry setting ',(0,r.jsx)(n.a,{href:"/api/config/build-config.html#dtsrespectexternal",children:(0,r.jsx)(n.code,{children:"dts.respectExternal"})})," to ",(0,r.jsx)(n.code,{children:"false"})," to turn off the behavior of packaging type files of third-party dependencies."]}),"\n",(0,r.jsxs)(n.h3,{id:"error-reported-for-defineconfig-function-type-if-there-is-no-reference-to--then-the-inferred-type-of-default-cannot-be-named",children:["Error reported for ",(0,r.jsx)(n.code,{children:"defineConfig"})," function type: ",(0,r.jsx)(n.code,{children:'If there is no reference to "..." then the inferred type of "default" cannot be named'}),(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#error-reported-for-defineconfig-function-type-if-there-is-no-reference-to--then-the-inferred-type-of-default-cannot-be-named",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["Check if the ",(0,r.jsx)(n.a,{href:"https://www.typescriptlang.org/tsconfig#include",target:"_blank",rel:"noopener noreferrer",children:(0,r.jsx)(n.code,{children:"include"})})," configuration exists in the project's tsconfig.json file, and if not, try adding the following:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "include": ["src"]\n}\n'})}),"\n",(0,r.jsxs)(n.h2,{id:"other-faq",children:["Other FAQ",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#other-faq",children:"#"})]}),"\n",(0,r.jsxs)(n.h3,{id:"how-to-skip-the-pre-processing-of-lessscss-files-with-bundleless",children:["How to skip the pre-processing of less/scss files with bundleless",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#how-to-skip-the-pre-processing-of-lessscss-files-with-bundleless",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["Bundleless is a single-file compilation method. You just need to remove your less/scss files from the entry and copy them to the output.\nNote that we will also rewrite the moduleId of js referencing less/scss, turn it off through the ",(0,r.jsx)(n.a,{href:"/api/config/build-config#redirect",children:"redirect"})," plugin."]}),"\n",(0,r.jsx)(n.p,{children:"Below is an example of skipping less file processing. You will find that all less files in src are copied to dist and the relative path is preserved."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",meta:'title="modern.config.ts"',children:"export default defineConfig({\n buildConfig: {\n buildType: 'bundleless',\n input: ['src', '!src/**/*.less'],\n redirect: {\n style: false,\n },\n copy: {\n patterns: [\n {\n from: './**/*.less',\n to: './',\n },\n ],\n options: {\n enableCopySync: true,\n },\n },\n },\n});\n"})}),"\n",(0,r.jsxs)(n.h3,{id:"add-additional-compilation-feature",children:["Add additional compilation feature",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#add-additional-compilation-feature",children:"#"})]}),"\n",(0,r.jsx)(n.p,{children:"The Modern.js Module is based on the esbuild implementation, so if you have special needs or want to add additional compilation capabilities, you can do so by implementing the esbuild plugin."}),"\n",(0,r.jsxs)(n.p,{children:["The Modern.js Module provides ",(0,r.jsx)(n.a,{href:"/api/config/build-config.html#esbuildoptions",children:(0,r.jsx)(n.code,{children:"esbuildOptions"})})," configuration to allow modification of Modern.js's internal esbuild configuration, so that custom esbuild plugins can be added via this configuration:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",meta:'title="modern.config.ts"',children:"import { myEsbuildPlugin } from './myEsbuildPlugin';\n\nexport default defineConfig({\n buildConfig: {\n esbuildOptions: options => {\n options.plugins = [myEsbuildPlugin, ...options.plugins];\n return options;\n },\n },\n});\n"})}),"\n",(0,r.jsx)(n.p,{children:"When adding an esbuild plugin, please note that you need to add the plugin at the beginning of the plugins array. This is because the Modern.js Module is also integrated into the entire build process through an esbuild plugin. Therefore, custom plugins need to be registered with higher priority."}),"\n",(0,r.jsxs)(n.h3,{id:"support-for-generating-typescript-declaration-files-for-css-modules",children:["Support for generating TypeScript declaration files for CSS Modules",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#support-for-generating-typescript-declaration-files-for-css-modules",children:"#"})]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["First Solution: ",(0,r.jsx)(n.a,{href:"https://github.com/Quramy/typed-css-modules",target:"_blank",rel:"noopener noreferrer",children:"typed-css-modules"})]}),"\n",(0,r.jsxs)(n.li,{children:["Second Solution: ",(0,r.jsx)(n.a,{href:"https://www.npmjs.com/package/@guanghechen/postcss-modules-dts",target:"_blank",rel:"noopener noreferrer",children:"postcss-modules-dts"})]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",meta:'title="modern.config.ts"',children:"import { defineConfig } from '@modern-js/module-tools';\n\nexport default defineConfig(async () => {\n const { dts } = await import('@guanghechen/postcss-modules-dts');\n return {\n buildConfig: {\n style: {\n modules: { ...dts },\n },\n },\n // custom config\n };\n});\n"})})]})}function t(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,s.ah)(),e.components);return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(o,{...e})}):o(e)}let d=t;t.__RSPRESS_PAGE_META={},t.__RSPRESS_PAGE_META["en%2Fguide%2Ffaq%2Fbuild.mdx"]={toc:[{text:"Product FAQ",id:"product-faq",depth:2},{text:"Initialization of Class Fields",id:"initialization-of-class-fields",depth:3},{text:"babel-plugin-lodash treats the introduced lodash as `undefined`",id:"babel-plugin-lodash-treats-the-introduced-lodash-as-undefined",depth:3},{text:"Cannot find module 'http'",id:"cannot-find-module-http",depth:3},{text:"Exceptions FAQ",id:"exceptions-faq",depth:2},{text:'Dynamic require of "react" is not supported',id:"dynamic-require-of-react-is-not-supported",depth:3},{text:"Problem Description",id:"problem-description",depth:4},{text:"Solution",id:"solution",depth:4},{text:"Reference Links",id:"reference-links",depth:4},{text:"During compilation, an error was reported in the less file of a component library:`'Operation on an invalid type'`",id:"during-compilation-an-error-was-reported-in-the-less-file-of-a-component-libraryoperation-on-an-invalid-type",depth:3},{text:"Bundleless DTS failed",id:"bundleless-dts-failed",depth:3},{text:"Bundle DTS failed",id:"bundle-dts-failed",depth:3},{text:'Error reported for `defineConfig` function type: `If there is no reference to "..." then the inferred type of "default" cannot be named`',id:"error-reported-for-defineconfig-function-type-if-there-is-no-reference-to--then-the-inferred-type-of-default-cannot-be-named",depth:3},{text:"Other FAQ",id:"other-faq",depth:2},{text:"How to skip the pre-processing of less/scss files with bundleless",id:"how-to-skip-the-pre-processing-of-lessscss-files-with-bundleless",depth:3},{text:"Add additional compilation feature",id:"add-additional-compilation-feature",depth:3},{text:"Support for generating TypeScript declaration files for CSS Modules",id:"support-for-generating-typescript-declaration-files-for-css-modules",depth:3}],title:"Build FAQ",frontmatter:{}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_modern_js_module_tools_docs=self.webpackChunk_modern_js_module_tools_docs||[]).push([["8802"],{4585:function(e,n,r){r.r(n),r.d(n,{default:function(){return l}});var s=r(8093),i=r(5878);function d(e){let n=Object.assign({h1:"h1",a:"a",p:"p",ul:"ul",li:"li",code:"code",strong:"strong",h2:"h2",div:"div",pre:"pre"},(0,i.ah)(),e.components);return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.h1,{id:"使用微生成器",children:["使用微生成器",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#使用微生成器",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"Modern.js Module 提供了微生成器工具,它可以为当前项目:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"新增目录和文件"}),"\n",(0,s.jsxs)(n.li,{children:["修改 ",(0,s.jsx)(n.code,{children:"package.json"})]}),"\n",(0,s.jsx)(n.li,{children:"执行命令"}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["因此通过这些能力,",(0,s.jsx)(n.strong,{children:"微生成器可以为项目开启额外的特性功能"}),"。"]}),"\n",(0,s.jsxs)(n.p,{children:["可以通过 ",(0,s.jsx)(n.a,{href:"/guide/basic/command-preview",children:(0,s.jsx)(n.code,{children:"modern new"})})," 启动微生成器。目前 Modern.js Module 支持的微生成器功能有:"]}),"\n",(0,s.jsxs)(n.h2,{id:"开发模块文档",children:["开发模块文档",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#开发模块文档",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["当我们想要为模块编写文档的时候,可以启用模块文档功能。",(0,s.jsxs)(n.strong,{children:["会在项目目录下创建 ",(0,s.jsx)(n.code,{children:"docs"})," 目录以及相关文件,在 package.json 中新增 ",(0,s.jsx)(n.code,{children:'"@modern-js/plugin-rspress"'})," 依赖"]}),"。\n使用 ",(0,s.jsx)(n.code,{children:"modern dev"})," 和 ",(0,s.jsx)(n.code,{children:"modern build --platform"})," 来调试和构建你的文档站点。"]}),"\n",(0,s.jsxs)(n.div,{className:"rspress-directive tip",children:[(0,s.jsx)(n.div,{className:"rspress-directive-title",children:"TIP"}),(0,s.jsxs)(n.div,{className:"rspress-directive-content",children:["\n",(0,s.jsx)(n.p,{children:"在成功开启后,会提示需要手动在配置中增加如下类似的代码。"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"import { moduleTools, defineConfig } from '@modern-js/module-tools';\nimport { modulePluginDoc } from '@modern-js/plugin-rspress';\n\nexport default defineConfig({\n plugins: [moduleTools(), modulePluginDoc()],\n});\n"})}),"\n"]})]}),"\n",(0,s.jsxs)(n.h2,{id:"storybook-调试",children:["Storybook 调试",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#storybook-调试",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["当我们想要对组件或者普通模块进行调试的时候,可以启用 Storybook 调试功能。启动该功能后,",(0,s.jsxs)(n.strong,{children:["会在项目目录下创建 ",(0,s.jsx)(n.code,{children:"stories"})," 目录以及 ",(0,s.jsx)(n.code,{children:".storybook"})," 目录,在 package.json 中新增 ",(0,s.jsx)(n.code,{children:'"@modern-js/storybook"'})," 依赖"]}),"。使用 ",(0,s.jsx)(n.code,{children:"storybook dev"})," 和 ",(0,s.jsx)(n.code,{children:"storybook build"})," 来调试和构建。"]}),"\n",(0,s.jsxs)(n.h2,{id:"tailwind-css-支持",children:["Tailwind CSS 支持",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#tailwind-css-支持",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.a,{href:"https://tailwindcss.com/",target:"_blank",rel:"noopener noreferrer",children:"Tailwind CSS"})," 是一个以 Utility Class 为基础的 CSS 框架和设计系统,可以快速地为组件添加常用样式,同时支持主题样式的灵活扩展。"]}),"\n",(0,s.jsxs)(n.p,{children:["如果你想要在项目使用 ",(0,s.jsx)(n.a,{href:"https://tailwindcss.com/",target:"_blank",rel:"noopener noreferrer",children:"Tailwind CSS"}),",可以参考 ",(0,s.jsx)(n.a,{href:"https://modernjs.dev/module-tools/guide/best-practices/components.html#tailwind-css",target:"_blank",rel:"noopener noreferrer",children:"「使用 Tailwind CSS」"}),"。"]}),"\n",(0,s.jsxs)(n.h2,{id:"modernjs-runtime-api-支持",children:["Modern.js Runtime API 支持",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#modernjs-runtime-api-支持",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsxs)(n.strong,{children:["Modern.js 提供了 ",(0,s.jsx)(n.a,{href:"https://modernjs.dev/configure/app/runtime/intro",target:"_blank",rel:"noopener noreferrer",children:"Runtime API"})," 能力,这些 API 只能在 Modern.js 的应用项目环境中使用"]}),"。如果你需要开发一个 Modern.js 应用环境中使用的组件,那么你可以开启该特性,微生成器会增加 ",(0,s.jsx)(n.code,{children:'"@modern-js/runtime"'}),"依赖。"]}),"\n",(0,s.jsx)(n.p,{children:"另外,Storybook 调试工具也会通过检测项目的依赖确定项目是否需要使用 Runtime API,并且提供与 Modern.js 应用项目一样的 Runtime API 运行环境。"}),"\n",(0,s.jsxs)(n.div,{className:"rspress-directive tip",children:[(0,s.jsx)(n.div,{className:"rspress-directive-title",children:"TIP"}),(0,s.jsxs)(n.div,{className:"rspress-directive-content",children:["\n",(0,s.jsx)(n.p,{children:"在成功开启后,会提示需要手动在配置中增加如下类似的代码。"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"import { moduleTools, defineConfig } from '@modern-js/module-tools';\nimport runtime from '@modern-js/runtime/cli';\n\nexport default defineConfig({\n plugins: [moduleTools(), runtime()],\n});\n"})}),"\n"]})]})]})}function o(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,i.ah)(),e.components);return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}let l=o;o.__RSPRESS_PAGE_META={},o.__RSPRESS_PAGE_META["zh%2Fguide%2Fbasic%2Fuse-micro-generator.md"]={toc:[{text:"开发模块文档",id:"开发模块文档",depth:2},{text:"Storybook 调试",id:"storybook-调试",depth:2},{text:"Tailwind CSS 支持",id:"tailwind-css-支持",depth:2},{text:"Modern.js Runtime API 支持",id:"modernjs-runtime-api-支持",depth:2}],title:"使用微生成器",frontmatter:{sidebar_position:4}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_modern_js_module_tools_docs=self.webpackChunk_modern_js_module_tools_docs||[]).push([["9100"],{191:function(e,l,n){n.r(l),n.d(l,{default:function(){return o}});var d=n(8093),i=n(5878),s=n(8078);function r(e){let l=Object.assign({h1:"h1",a:"a",div:"div",p:"p",h2:"h2",h3:"h3",pre:"pre",code:"code",ul:"ul",li:"li",strong:"strong"},(0,i.ah)(),e.components);return(0,d.jsxs)(d.Fragment,{children:[(0,d.jsxs)(l.h1,{id:"node-polyfill-插件",children:["Node Polyfill 插件",(0,d.jsx)(l.a,{className:"header-anchor","aria-hidden":"true",href:"#node-polyfill-插件",children:"#"})]}),"\n",(0,d.jsxs)(l.div,{className:"rspress-directive tip",children:[(0,d.jsx)(l.div,{className:"rspress-directive-title",children:"Node Polyfill 介绍"}),(0,d.jsx)(l.div,{className:"rspress-directive-content",children:(0,d.jsx)(l.p,{children:"通常情况下,我们不会在浏览器端使用 Node 模块。但在当前代码需要同时在 Node 端和浏览器端运行时,用到一些 Node 模块是有可能的。Node Polyfill 为这些 Node 模块提供了浏览器版本的 polyfills。"})})]}),"\n",(0,d.jsx)(l.p,{children:"通过使用 Node Polyfill 插件,会自动注入 Node 核心模块在浏览器端的 polyfills,让你可以在浏览器端放心使用这些模块。"}),"\n",(0,d.jsxs)(l.h2,{id:"快速开始",children:["快速开始",(0,d.jsx)(l.a,{className:"header-anchor","aria-hidden":"true",href:"#快速开始",children:"#"})]}),"\n",(0,d.jsxs)(l.h3,{id:"安装",children:["安装",(0,d.jsx)(l.a,{className:"header-anchor","aria-hidden":"true",href:"#安装",children:"#"})]}),"\n","\n",(0,d.jsx)(s.SU,{command:"add @modern-js/plugin-module-node-polyfill -D"}),"\n",(0,d.jsxs)(l.h3,{id:"注册插件",children:["注册插件",(0,d.jsx)(l.a,{className:"header-anchor","aria-hidden":"true",href:"#注册插件",children:"#"})]}),"\n",(0,d.jsx)(l.p,{children:"在 Modern.js Module 中,你可以按照如下方式注册插件:"}),"\n",(0,d.jsx)(l.pre,{children:(0,d.jsx)(l.code,{className:"language-ts",children:"import { moduleTools, defineConfig } from '@modern-js/module-tools';\nimport { modulePluginNodePolyfill } from '@modern-js/plugin-module-node-polyfill';\n\nexport default defineConfig({\n plugins: [moduleTools(), modulePluginNodePolyfill()],\n});\n"})}),"\n",(0,d.jsxs)(l.h2,{id:"配置",children:["配置",(0,d.jsx)(l.a,{className:"header-anchor","aria-hidden":"true",href:"#配置",children:"#"})]}),"\n",(0,d.jsxs)(l.ul,{children:["\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.strong,{children:"类型:"})}),"\n"]}),"\n",(0,d.jsx)(l.pre,{children:(0,d.jsx)(l.code,{className:"language-ts",children:"type NodePolyfillOptions = {\n exclude?: string[];\n overrides?: Record<NodePolyfillKey, string>;\n};\n"})}),"\n",(0,d.jsxs)(l.h3,{id:"exclude",children:["exclude",(0,d.jsx)(l.a,{className:"header-anchor","aria-hidden":"true",href:"#exclude",children:"#"})]}),"\n",(0,d.jsx)(l.p,{children:"排除要注入的 Node Polyfill。"}),"\n",(0,d.jsx)(l.pre,{children:(0,d.jsx)(l.code,{className:"language-ts",children:"import { moduleTools, defineConfig } from '@modern-js/module-tools';\nimport { modulePluginNodePolyfill } from '@modern-js/plugin-module-node-polyfill';\n\nexport default defineConfig({\n plugins: [\n moduleTools(),\n modulePluginNodePolyfill({\n exclude: ['console'],\n }),\n ],\n});\n"})}),"\n",(0,d.jsxs)(l.h3,{id:"overrides",children:["overrides",(0,d.jsx)(l.a,{className:"header-anchor","aria-hidden":"true",href:"#overrides",children:"#"})]}),"\n",(0,d.jsx)(l.p,{children:"覆盖内置的 Node Polyfill。"}),"\n",(0,d.jsx)(l.pre,{children:(0,d.jsx)(l.code,{className:"language-ts",children:"import { moduleTools, defineConfig } from '@modern-js/module-tools';\nimport { modulePluginNodePolyfill } from '@modern-js/plugin-module-node-polyfill';\n\nexport default defineConfig({\n plugins: [\n moduleTools(),\n modulePluginNodePolyfill({\n overrides: {\n fs: path.join(__dirname, './custom-fs.js'),\n },\n }),\n ],\n});\n"})}),"\n",(0,d.jsxs)(l.h2,{id:"node-polyfills",children:["Node Polyfills",(0,d.jsx)(l.a,{className:"header-anchor","aria-hidden":"true",href:"#node-polyfills",children:"#"})]}),"\n",(0,d.jsxs)(l.h3,{id:"globals",children:["Globals",(0,d.jsx)(l.a,{className:"header-anchor","aria-hidden":"true",href:"#globals",children:"#"})]}),"\n",(0,d.jsxs)(l.ul,{children:["\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"Buffer"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"process"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"console"})}),"\n"]}),"\n",(0,d.jsx)(l.p,{children:"当你在代码中使用以上全局变量时,对应 polyfill 会被自动注入。"}),"\n",(0,d.jsx)(l.pre,{children:(0,d.jsx)(l.code,{className:"language-ts",children:"const bufferData = Buffer.from('xxxx');\n"})}),"\n",(0,d.jsxs)(l.h3,{id:"modules",children:["Modules",(0,d.jsx)(l.a,{className:"header-anchor","aria-hidden":"true",href:"#modules",children:"#"})]}),"\n",(0,d.jsxs)(l.ul,{children:["\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"assert"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"buffer"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"console"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"constants"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"crypto"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"domain"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"events"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"http"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"https"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"os"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"path"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"punycode"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"process"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"querystring"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"stream"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"_stream_duplex"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"_stream_passthrough"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"_stream_readable"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"_stream_transform"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"_stream_writable"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"string_decoder"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"sys"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"timers"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"tty"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"url"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"util"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"vm"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"zlib"})}),"\n"]}),"\n",(0,d.jsxs)(l.p,{children:["当你通过 ",(0,d.jsx)(l.code,{children:"require"})," 或 ",(0,d.jsx)(l.code,{children:"import"})," 等语法在代码中引用以上模块时,对应 polyfill 会被注入。"]}),"\n",(0,d.jsx)(l.pre,{children:(0,d.jsx)(l.code,{className:"language-ts",children:"import { Buffer } from 'buffer';\n\nconst bufferData = Buffer.from('xxxx');\n"})}),"\n",(0,d.jsxs)(l.h3,{id:"fallbacks",children:["Fallbacks",(0,d.jsx)(l.a,{className:"header-anchor","aria-hidden":"true",href:"#fallbacks",children:"#"})]}),"\n",(0,d.jsxs)(l.ul,{children:["\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"child_process"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"cluster"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"dgram"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"dns"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"fs"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"module"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"net"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"readline"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"repl"})}),"\n",(0,d.jsx)(l.li,{children:(0,d.jsx)(l.code,{children:"tls"})}),"\n"]}),"\n",(0,d.jsx)(l.p,{children:"目前浏览器端没有以上模块的 polyfill,因此当你引用以上模块时,会自动 fallback 为一个空对象。"}),"\n",(0,d.jsx)(l.pre,{children:(0,d.jsx)(l.code,{className:"language-ts",children:"import fs from 'fs';\n\nconsole.log(fs); // -> {}\n"})})]})}function c(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:l}=Object.assign({},(0,i.ah)(),e.components);return l?(0,d.jsx)(l,{...e,children:(0,d.jsx)(r,{...e})}):r(e)}let o=c;c.__RSPRESS_PAGE_META={},c.__RSPRESS_PAGE_META["zh%2Fplugins%2Fofficial-list%2Fplugin-node-polyfill.mdx"]={toc:[{text:"快速开始",id:"快速开始",depth:2},{text:"安装",id:"安装",depth:3},{text:"注册插件",id:"注册插件",depth:3},{text:"配置",id:"配置",depth:2},{text:"exclude",id:"exclude",depth:3},{text:"overrides",id:"overrides",depth:3},{text:"Node Polyfills",id:"node-polyfills",depth:2},{text:"Globals",id:"globals",depth:3},{text:"Modules",id:"modules",depth:3},{text:"Fallbacks",id:"fallbacks",depth:3}],title:"Node Polyfill 插件",frontmatter:{}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_modern_js_module_tools_docs=self.webpackChunk_modern_js_module_tools_docs||[]).push([["9250"],{1459:function(e,n,s){s.r(n),s.d(n,{default:function(){return c}});var r=s(8093),i=s(5878);function d(e){let n=Object.assign({h1:"h1",a:"a",p:"p",code:"code",div:"div",h2:"h2",strong:"strong",ul:"ul",li:"li",pre:"pre",h3:"h3",h4:"h4"},(0,i.ah)(),e.components);return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.h1,{id:"深入理解构建",children:["深入理解构建",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#深入理解构建",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:['在 "基础使用" 的部分,我们已经知道可以通过 ',(0,r.jsx)(n.code,{children:"buildConfig"})," 配置对项目的输出产物进行修改。",(0,r.jsx)(n.code,{children:"buildConfig"})," 不仅描述了产物的一些特性,同时还为构建产物提供了一些功能。"]}),"\n",(0,r.jsxs)(n.div,{className:"rspress-directive tip",children:[(0,r.jsx)(n.div,{className:"rspress-directive-title",children:"TIP"}),(0,r.jsx)(n.div,{className:"rspress-directive-content",children:(0,r.jsxs)(n.p,{children:["如果你还不了解 ",(0,r.jsx)(n.code,{children:"buildConfig"})," 的作用,请先阅读 ",(0,r.jsx)(n.a,{href:"/guide/basic/modify-output-product",children:"修改输出产物"}),"。\n"]})})]}),"\n",(0,r.jsxs)(n.p,{children:["而在本章里我们将要深入理解某些构建配置的作用以及了解执行 ",(0,r.jsx)(n.code,{children:"modern build"})," 命令的时候发生了什么。"]}),"\n",(0,r.jsxs)(n.h2,{id:"bundle--bundleless",children:[(0,r.jsx)(n.code,{children:"bundle"})," / ",(0,r.jsx)(n.code,{children:"bundleless"}),(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#bundle--bundleless",children:"#"})]}),"\n",(0,r.jsx)(n.p,{children:"那么首先我们来了解一下 bundle 和 bundleless。"}),"\n",(0,r.jsxs)(n.p,{children:["所谓 bundle 是指对构建产物进行打包,构建产物可能是一个文件,也有可能是基于一定的",(0,r.jsx)(n.a,{href:"https://esbuild.github.io/api/#splitting",target:"_blank",rel:"noopener noreferrer",children:"代码拆分策略"}),"得到的多个文件。"]}),"\n",(0,r.jsxs)(n.p,{children:["而 bundleless 则是指对每个源文件单独进行编译构建,但是并不将它们打包在一起。每一个产物文件都可以找到与之相对应的源码文件。",(0,r.jsx)(n.strong,{children:"bundleless 构建的过程,也可以理解为仅对源文件进行代码转换的过程"}),"。"]}),"\n",(0,r.jsx)(n.p,{children:"它们有各自的好处:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"bundle 可以减少构建产物的体积,也可以对依赖预打包,减小安装依赖的体积。提前对库进行打包,可以加快应用项目构建的速度。"}),"\n",(0,r.jsx)(n.li,{children:"bundleless 则是可以保持原有的文件结构,更有利于调试和 tree shaking。"}),"\n"]}),"\n",(0,r.jsxs)(n.div,{className:"rspress-directive warning",children:[(0,r.jsx)(n.div,{className:"rspress-directive-title",children:"WARNING"}),(0,r.jsx)(n.div,{className:"rspress-directive-content",children:(0,r.jsxs)(n.p,{children:["bundleless 是单文件编译模式,因此对于类型的引用和导出你需要加上 ",(0,r.jsx)(n.code,{children:"type"})," 字段, 例如 ",(0,r.jsx)(n.code,{children:"import type { A } from './types"}),",背景参考 ",(0,r.jsx)(n.a,{href:"https://esbuild.github.io/content-types/#isolated-modules",target:"_blank",rel:"noopener noreferrer",children:"esbuild 文档"}),"。\n"]})})]}),"\n",(0,r.jsxs)(n.p,{children:["在 ",(0,r.jsx)(n.code,{children:"buildConfig"})," 中可以通过 ",(0,r.jsx)(n.a,{href:"/api/config/build-config#buildtype",children:(0,r.jsx)(n.code,{children:"buildConfig.buildType"})})," 来指定当前构建任务是 bundle 还是 bundleless。"]}),"\n",(0,r.jsxs)(n.h2,{id:"input--sourcedir",children:[(0,r.jsx)(n.code,{children:"input"})," / ",(0,r.jsx)(n.code,{children:"sourceDir"}),(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#input--sourcedir",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"/api/config/build-config#input",children:(0,r.jsx)(n.code,{children:"buildConfig.input"})})," 用于指定读取源码的文件路径或者目录路径,其默认值在 bundle 和 bundleless 构建过程中有所不同:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["当 ",(0,r.jsx)(n.code,{children:"buildType: 'bundle'"})," 的时候,",(0,r.jsx)(n.code,{children:"input"})," 默认值为 ",(0,r.jsx)(n.code,{children:"src/index.(j|t)sx?"})]}),"\n",(0,r.jsxs)(n.li,{children:["当 ",(0,r.jsx)(n.code,{children:"buildType: 'bundleless'"})," 的时候,",(0,r.jsx)(n.code,{children:"input"})," 默认值为 ",(0,r.jsx)(n.code,{children:"['src']"})]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["从默认值上我们可以知道:",(0,r.jsx)(n.strong,{children:"使用 bundle 模式构建时一般指定一个或多个文件作为构建的入口,而使用 bundleless 构建则是指定一个目录,将目录下所有文件作为入口"}),"。"]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"/api/config/build-config#sourcedir",children:(0,r.jsx)(n.code,{children:"sourceDir"})})," 用于指定源码目录,它",(0,r.jsx)(n.strong,{children:"只与"}),"以下两个内容有关系:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"类型文件生成"}),"\n",(0,r.jsxs)(n.li,{children:["指定构建过程中的 ",(0,r.jsx)(n.a,{href:"https://esbuild.github.io/api/#outbase",target:"_blank",rel:"noopener noreferrer",children:(0,r.jsx)(n.code,{children:"outbase"})})]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"因此我们可以得到其最佳实践:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsxs)(n.strong,{children:["在 bundle 构建过程中,只能指定 ",(0,r.jsx)(n.code,{children:"input"})," 。"]})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsxs)(n.strong,{children:["一般情况下,bundleless 只需要指定 ",(0,r.jsx)(n.code,{children:"sourceDir"}),"(此时 ",(0,r.jsx)(n.code,{children:"input"})," 会与 ",(0,r.jsx)(n.code,{children:"sourceDir"})," 保持一致)。"]})}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["如果我们想要在 bundleless 里只对一部分文件进行转换,例如只需要转换 ",(0,r.jsx)(n.code,{children:"src/runtime"})," 目录的文件,此时需要配置 ",(0,r.jsx)(n.code,{children:"input"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",meta:'title="modern.config.ts"',children:"import { defineConfig } from '@modern-js/module-tools';\n\nexport default defineConfig({\n buildConfig: {\n input: ['src/runtime'],\n sourceDir: 'src',\n },\n});\n"})}),"\n",(0,r.jsxs)(n.h2,{id:"使用-swc",children:["使用 swc",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#使用-swc",children:"#"})]}),"\n",(0,r.jsx)(n.p,{children:"在部分场景下,esbuild 不足以满足我们的需求,此时我们会使用 swc 来做代码转换。"}),"\n",(0,r.jsxs)(n.p,{children:["从 ",(0,r.jsx)(n.strong,{children:"2.36.0"})," 版本开始,涉及到以下功能时,Modern.js Module 默认会使用 swc ,但不这意味着不使用 esbuild 了,其余功能还是使用 esbuild:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/api/config/build-config#transformimport",children:"transformImport"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/api/config/build-config#transformlodash",children:"transformLodash"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/api/config/build-config#externalhelpers",children:"externalHelpers"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/api/config/build-config#format-umd",children:"format: umd"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/api/config/build-config#target",children:"target: es5"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://www.typescriptlang.org/tsconfig#emitDecoratorMetadata",target:"_blank",rel:"noopener noreferrer",children:"emitDecoratorMetadata: true"})}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["事实上,我们在 ",(0,r.jsx)(n.strong,{children:"2.16.0"})," 版本开始全量使用 swc 进行代码转换。不过 swc 同样也存在一些限制,为此我们添加了 ",(0,r.jsx)(n.a,{href:"/api/config/build-config#sourcetype",children:"sourceType"})," 配置,当源码格式为 'commonjs' 时关闭 swc, 但这种方式并不符合用户直觉,另外,swc 格式化输出的 cjs 模式没有给每个导出名称添加注释,这在 node 中使用可能会带来一些问题。\n因为我们废弃了此行为,回到了最初的设计 - ",(0,r.jsx)(n.strong,{children:"只在需要的场景下使用 swc 作为补充"}),"。"]}),"\n",(0,r.jsxs)(n.h2,{id:"使用-hook-介入构建流程",children:["使用 Hook 介入构建流程",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#使用-hook-介入构建流程",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["Modern.js Module 提供了 Hook 机制,允许我们在构建流程的不同阶段注入自定义逻辑。\nModern.js Module Hook 使用了 ",(0,r.jsx)(n.a,{href:"https://github.com/webpack/tapable",target:"_blank",rel:"noopener noreferrer",children:"tapable"})," 实现,扩展了 esbuild 的插件机制,若 esbuild plugins 已经满足了你的需求,建议直接使用它。\n下面展开说明其用法:"]}),"\n",(0,r.jsxs)(n.h3,{id:"hook-类型",children:["Hook 类型",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#hook-类型",children:"#"})]}),"\n",(0,r.jsxs)(n.h4,{id:"asyncseriesbailhook",children:["AsyncSeriesBailHook",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#asyncseriesbailhook",children:"#"})]}),"\n",(0,r.jsx)(n.p,{children:"串行执行的 hooks,如果某个 tapped function 返回非 undefined 结果,则后续其他的 tapped function 停止执行。"}),"\n",(0,r.jsxs)(n.h4,{id:"asyncserieswaterfallhooks",children:["AsyncSeriesWaterFallHooks",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#asyncserieswaterfallhooks",children:"#"})]}),"\n",(0,r.jsx)(n.p,{children:"串行执行的 hooks,其结果会传递给下一个 tapped function"}),"\n",(0,r.jsxs)(n.h3,{id:"hook-顺序",children:["Hook 顺序",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#hook-顺序",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["Hook 的执行顺序和注册顺序保持一致,可以通过 ",(0,r.jsx)(n.code,{children:"applyAfterBuiltIn"})," 来控制在 BuiltIn Hook 前或后注册。"]}),"\n",(0,r.jsxs)(n.h3,{id:"hook-api",children:["Hook API",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#hook-api",children:"#"})]}),"\n",(0,r.jsxs)(n.h4,{id:"load",children:["load",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#load",children:"#"})]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"AsyncSeriesBailHook"}),"\n",(0,r.jsxs)(n.li,{children:["在 esbuild ",(0,r.jsx)(n.a,{href:"https://esbuild.github.io/plugins/#on-load",target:"_blank",rel:"noopener noreferrer",children:"onLoad callbacks"})," 触发,根据模块路径来获取模块内容"]}),"\n",(0,r.jsx)(n.li,{children:"输入参数"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"interface LoadArgs {\n path: string;\n namespace: string;\n suffix: string;\n}\n"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"返回参数"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"type LoadResult =\n | {\n contents: string; // 模块内容\n map?: SourceMap; // https://esbuild.github.io/api/#sourcemap\n loader?: Loader; // https://esbuild.github.io/api/#loader\n resolveDir?: string;\n }\n | undefined;\n"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"例子"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"compiler.hooks.load.tapPromise('load content from memfs', async args => {\n const contents = memfs.readFileSync(args.path);\n return {\n contents: contents,\n loader: 'js',\n };\n});\n"})}),"\n",(0,r.jsxs)(n.h4,{id:"transform",children:["transform",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#transform",children:"#"})]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"AsyncSeriesWaterFallHooks"}),"\n",(0,r.jsxs)(n.li,{children:["在 esbuild ",(0,r.jsx)(n.a,{href:"https://esbuild.github.io/plugins/#on-load",target:"_blank",rel:"noopener noreferrer",children:"onLoad callbacks"})," 触发,\n将 load 阶段获取的模块内容进行转换"]}),"\n",(0,r.jsx)(n.li,{children:"输入参数(返回参数)"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"export type Source = {\n code: string;\n map?: SourceMap;\n path: string;\n loader?: string;\n};\n"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"例子"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"compiler.hooks.transform.tapPromise('6to5', async args => {\n const result = babelTransform(args.code, { presets: ['@babel/preset-env'] });\n return {\n code: result.code,\n map: result.map,\n };\n});\n"})}),"\n",(0,r.jsxs)(n.h4,{id:"renderchunk",children:["renderChunk",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#renderchunk",children:"#"})]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"AsyncSeriesWaterFallHooks"}),"\n",(0,r.jsxs)(n.li,{children:["在 esbuild ",(0,r.jsx)(n.a,{href:"https://esbuild.github.io/plugins/#on-end",target:"_blank",rel:"noopener noreferrer",children:"onEnd callbacks"})," 触发,\n类似于 transform hook,但是作用在 esbuild 生成的产物"]}),"\n",(0,r.jsx)(n.li,{children:"输入参数(返回参数)"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"export type AssetChunk = {\n type: 'asset';\n contents: string | Buffer;\n entryPoint?: string;\n /**\n * absolute file path\n */\n fileName: string;\n originalFileName?: string;\n};\n\nexport type JsChunk = {\n type: 'chunk';\n contents: string;\n entryPoint?: string;\n /**\n * absolute file path\n */\n fileName: string;\n map?: SourceMap;\n modules?: Record<string, any>;\n originalFileName?: string;\n};\n\nexport type Chunk = AssetChunk | JsChunk;\n"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"例子"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"compiler.hooks.renderChunk.tapPromise('minify', async chunk => {\n if (chunk.type === 'chunk') {\n const code = chunk.contents.toString();\n const result = await minify.call(compiler, code);\n return {\n ...chunk,\n contents: result.code,\n map: result.map,\n };\n }\n return chunk;\n});\n"})}),"\n",(0,r.jsxs)(n.h2,{id:"类型文件生成",children:["类型文件生成",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#类型文件生成",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"/api/config/build-config#dts",children:(0,r.jsx)(n.code,{children:"buildConfig.dts"})})," 配置主要用于类型文件的生成。"]}),"\n",(0,r.jsxs)(n.h3,{id:"关闭类型生成",children:["关闭类型生成",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#关闭类型生成",children:"#"})]}),"\n",(0,r.jsx)(n.p,{children:"默认情况下类型生成功能是开启的,如果需要关闭的话,可以按照如下配置:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",meta:'title="modern.config.ts"',children:"import { defineConfig } from '@modern-js/module-tools';\n\nexport default defineConfig({\n buildConfig: {\n dts: false,\n },\n});\n"})}),"\n",(0,r.jsxs)(n.div,{className:"rspress-directive tip",children:[(0,r.jsx)(n.div,{className:"rspress-directive-title",children:"TIP"}),(0,r.jsx)(n.div,{className:"rspress-directive-content",children:(0,r.jsx)(n.p,{children:"关闭类型文件后,一般来说构建速度会有所提升。"})})]}),"\n",(0,r.jsxs)(n.h3,{id:"打包类型文件",children:["打包类型文件",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#打包类型文件",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["在 ",(0,r.jsx)(n.code,{children:"buildType: 'bundleless'"})," 的时候,类型文件的生成是使用项目的 ",(0,r.jsx)(n.code,{children:"tsc"})," 命令来完成生产。"]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Modern.js Module 同时还支持对类型文件进行打包"}),",不过使用该功能的时候需要注意:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"对类型文件进行打包不会开启类型检查。"}),"\n",(0,r.jsxs)(n.li,{children:["一些第三方依赖存在错误的语法会导致打包过程失败。因此对于这种情况,需要手动通过 ",(0,r.jsx)(n.a,{href:"/api/config/build-config#externals",children:(0,r.jsx)(n.code,{children:"buildConfig.externals"})})," 将这类第三方包排除,或者直接关闭",(0,r.jsx)(n.a,{href:"/api/config/build-config#dtsrespectexternal",children:"dts.respectExternal"}),"从而不打包任何三方包类型。"]}),"\n",(0,r.jsxs)(n.li,{children:["对于第三方依赖的类型文件指向的是一个 ",(0,r.jsx)(n.code,{children:".ts"})," 文件的情况,目前无法处理。比如第三方依赖的 ",(0,r.jsx)(n.code,{children:"package.json"})," 中存在这样的内容: ",(0,r.jsx)(n.code,{children:'{"types": "./src/index.ts"'}),"。"]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["对于上述问题,我们推荐的处理方式是首先使用 ",(0,r.jsx)(n.code,{children:"tsc"})," 生成 d.ts 文件,然后将 index.d.ts 作为入口进行打包处理,并且关闭 ",(0,r.jsx)(n.code,{children:"dts.respectExternal"}),"。在之后的演进我们也会逐渐向这种处理方式靠拢。"]}),"\n",(0,r.jsxs)(n.h3,{id:"别名转换",children:["别名转换",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#别名转换",children:"#"})]}),"\n",(0,r.jsx)(n.p,{children:"在 bundleless 构建过程中,如果源代码中出现了别名,例如:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",meta:'title="./src/index.ts"',children:"import utils from '@common/utils';\n"})}),"\n",(0,r.jsxs)(n.p,{children:["使用 ",(0,r.jsx)(n.code,{children:"tsc"})," 生成的产物类型文件也会包含这些别名。不过 Modern.js Module 会对 ",(0,r.jsx)(n.code,{children:"tsc"})," 生成的类型文件里的别名进行转换处理。"]}),"\n",(0,r.jsxs)(n.h3,{id:"一些示例",children:["一些示例",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#一些示例",children:"#"})]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:"import { defineConfig } from '@modern-js/module-tools';\n\nexport default defineConfig({\n // 此时打包的类型文件输出路径为 `./dist/types`,并且将会读取项目下的 other-tsconfig.json 文件\n buildConfig: {\n buildType: 'bundle',\n dts: {\n tsconfigPath: './other-tsconfig.json',\n distPath: './types',\n },\n outDir: './dist',\n },\n});\n"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:"import { defineConfig } from '@modern-js/module-tools';\n\nexport default defineConfig({\n // 此时类型文件没有进行打包,输出路径为 `./dist/types`\n buildConfig: [\n {\n buildType: 'bundle',\n dts: false,\n outDir: './dist',\n },\n {\n buildType: 'bundleless',\n dts: {\n only: true,\n },\n outDir: './dist/types',\n },\n ],\n});\n"})}),"\n",(0,r.jsxs)(n.h2,{id:"构建过程",children:["构建过程",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#构建过程",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["当执行 ",(0,r.jsx)(n.code,{children:"modern build"})," 命令的时候,会发生"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["根据 ",(0,r.jsx)(n.code,{children:"buildConfig.outDir"})," 清理产物目录。"]}),"\n",(0,r.jsxs)(n.li,{children:["编译 ",(0,r.jsx)(n.code,{children:"js/ts"})," 源代码生成 bundle / bundleless 的 JS 构建产物。"]}),"\n",(0,r.jsxs)(n.li,{children:["使用 ",(0,r.jsx)(n.code,{children:"tsc"})," 生成 bundle / bundleless 的类型文件。"]}),"\n",(0,r.jsxs)(n.li,{children:["处理 ",(0,r.jsx)(n.code,{children:"copy"})," 任务。"]}),"\n"]}),"\n",(0,r.jsxs)(n.h2,{id:"构建报错",children:["构建报错",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#构建报错",children:"#"})]}),"\n",(0,r.jsx)(n.p,{children:"当发生构建报错的时候,基于以上了解到的信息,可以很容易的明白在终端出现的报错内容:"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"js 或者 ts 构建的报错:"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'error ModuleBuildError:\n\n╭───────────────────────╮\n│ bundle failed: │\n│ - format is "cjs" │\n│ - target is "esnext" │\n╰───────────────────────╯\n\nDetailed Information:\n'})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"类型文件生成过程的报错:"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"error ModuleBuildError:\n\nbundle DTS failed:\n"})}),"\n",(0,r.jsxs)(n.p,{children:["对于 ",(0,r.jsx)(n.code,{children:"js/ts"})," 构建错误,我们可以从报错信息中知道:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["报错的 ",(0,r.jsx)(n.code,{children:"buildType"})]}),"\n",(0,r.jsxs)(n.li,{children:["报错的 ",(0,r.jsx)(n.code,{children:"format"})]}),"\n",(0,r.jsxs)(n.li,{children:["报错的 ",(0,r.jsx)(n.code,{children:"target"})]}),"\n",(0,r.jsx)(n.li,{children:"其他具体报错信息"}),"\n"]}),"\n",(0,r.jsxs)(n.h2,{id:"调试模式",children:["调试模式",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#调试模式",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["从 ",(0,r.jsx)(n.strong,{children:"2.36.0"})," 版本开始,为了便于排查问题,Modern.js Module 提供了调试模式,你可以在执行构建时添加 DEBUG=module 环境变量来开启调试模式。"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"DEBUG=module modern build\n"})}),"\n",(0,r.jsx)(n.p,{children:"调试模式下,你会看到 Shell 中输出更详细的构建日志,这主要以流程日志为主:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"module run beforeBuildTask hooks +6ms\nmodule run beforeBuildTask hooks done +0ms\nmodule [DTS] Build Start +139ms\nmodule [CJS] Build Start +1ms\n"})}),"\n",(0,r.jsxs)(n.p,{children:["另外,Module 还提供了调试内部工作流程的能力。你可以通过设置环境变量 ",(0,r.jsx)(n.code,{children:"DEBUG=module:*"})," 来开启更详细的调试日志:"]}),"\n",(0,r.jsxs)(n.p,{children:["目前只支持了 ",(0,r.jsx)(n.code,{children:"DEBUG=module:resolve"}),",可以查看 Module 内部模块解析的详细日志:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:" module:resolve onResolve args: {\n path: './src/hooks/misc.ts',\n importer: '',\n namespace: 'file',\n resolveDir: '/Users/bytedance/modern.js/packages/solutions/module-tools',\n kind: 'entry-point',\n pluginData: undefined\n} +0ms\n module:resolve onResolve result: {\n path: '/Users/bytedance/modern.js/packages/solutions/module-tools/src/hooks/misc.ts',\n external: false,\n namespace: 'file',\n sideEffects: undefined,\n suffix: ''\n} +0ms\n"})})]})}function l(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,i.ah)(),e.components);return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}let c=l;l.__RSPRESS_PAGE_META={},l.__RSPRESS_PAGE_META["zh%2Fguide%2Fadvance%2Fin-depth-about-build.md"]={toc:[{text:"`bundle` / `bundleless`",id:"bundle--bundleless",depth:2},{text:"`input` / `sourceDir`",id:"input--sourcedir",depth:2},{text:"使用 swc",id:"使用-swc",depth:2},{text:"使用 Hook 介入构建流程",id:"使用-hook-介入构建流程",depth:2},{text:"Hook 类型",id:"hook-类型",depth:3},{text:"AsyncSeriesBailHook",id:"asyncseriesbailhook",depth:4},{text:"AsyncSeriesWaterFallHooks",id:"asyncserieswaterfallhooks",depth:4},{text:"Hook 顺序",id:"hook-顺序",depth:3},{text:"Hook API",id:"hook-api",depth:3},{text:"load",id:"load",depth:4},{text:"transform",id:"transform",depth:4},{text:"renderChunk",id:"renderchunk",depth:4},{text:"类型文件生成",id:"类型文件生成",depth:2},{text:"关闭类型生成",id:"关闭类型生成",depth:3},{text:"打包类型文件",id:"打包类型文件",depth:3},{text:"别名转换",id:"别名转换",depth:3},{text:"一些示例",id:"一些示例",depth:3},{text:"构建过程",id:"构建过程",depth:2},{text:"构建报错",id:"构建报错",depth:2},{text:"调试模式",id:"调试模式",depth:2}],title:"深入理解构建",frontmatter:{sidebar_position:1}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_modern_js_module_tools_docs=self.webpackChunk_modern_js_module_tools_docs||[]).push([["9524"],{7293:function(e,n,s){s.r(n),s.d(n,{default:function(){return l}});var r=s(8093),d=s(5878);function i(e){let n=Object.assign({h1:"h1",a:"a",p:"p",ul:"ul",li:"li",code:"code",h2:"h2",div:"div",pre:"pre",em:"em"},(0,d.ah)(),e.components);return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.h1,{id:"buildpreset",children:["buildPreset",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#buildpreset",children:"#"})]}),"\n",(0,r.jsx)(n.p,{children:"构建的预设字符串或者预设函数。提供开箱即用的构建配置。"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["类型:",(0,r.jsx)(n.code,{children:"string | Function"})]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["默认值: ",(0,r.jsx)(n.code,{children:"undefined"})]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.h2,{id:"npm-library",children:[(0,r.jsx)(n.code,{children:"npm-library"}),(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#npm-library",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["在类 ",(0,r.jsx)(n.a,{href:"https://www.npmjs.com/",target:"_blank",rel:"noopener noreferrer",children:"NPM"})," 包管理器下使用的 Library 通用模式,包含 ",(0,r.jsx)(n.code,{children:"esm"})," 和 ",(0,r.jsx)(n.code,{children:"cjs"})," 两种 Bundle 产物,并且包含一份类型文件。"]}),"\n",(0,r.jsxs)(n.div,{className:"rspress-directive info",children:[(0,r.jsx)(n.div,{className:"rspress-directive-title",children:"INFO"}),(0,r.jsxs)(n.div,{className:"rspress-directive-content",children:[(0,r.jsxs)(n.p,{children:["关于类 ",(0,r.jsx)(n.a,{href:"https://www.npmjs.com/",target:"_blank",rel:"noopener noreferrer",children:"NPM"})," 包管理器"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://www.npmjs.com",target:"_blank",rel:"noopener noreferrer",children:"npm"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://yarnpkg.com/",target:"_blank",rel:"noopener noreferrer",children:"yarn"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://pnpm.io/",target:"_blank",rel:"noopener noreferrer",children:"pnpm"})}),"\n"]}),"\n"]})]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",meta:'title="package.json"',children:'{\n "main": "./dist/lib/index.js",\n "module": "./dist/es/index.js",\n "types": "./dist/types/index.d.ts"\n}\n'})}),"\n",(0,r.jsx)(n.p,{children:"预设字符串对应的构建配置:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:"export const buildConfig = [\n {\n format: 'cjs',\n target: 'es6',\n buildType: 'bundle',\n outDir: './dist/lib',\n dts: false,\n },\n {\n format: 'esm',\n target: 'es6',\n buildType: 'bundle',\n outDir: './dist/es',\n dts: false,\n },\n {\n buildType: 'bundle',\n outDir: './dist/types',\n dts: {\n only: true,\n },\n },\n];\n"})}),"\n",(0,r.jsxs)(n.h2,{id:"npm-library-with-umd",children:[(0,r.jsx)(n.code,{children:"npm-library-with-umd"}),(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#npm-library-with-umd",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["在类 ",(0,r.jsx)(n.a,{href:"https://www.npmjs.com/",target:"_blank",rel:"noopener noreferrer",children:"NPM"})," 包管理器下使用,并且 Library 支持类似 ",(0,r.jsx)(n.a,{href:"https://unpkg.com/",target:"_blank",rel:"noopener noreferrer",children:"unpkg"})," 的模式。在预设 ",(0,r.jsx)(n.code,{children:"'npm-library'"})," 的基础上,额外提供 ",(0,r.jsx)(n.code,{children:"umd"})," 产物。"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",meta:'title="package.json"',children:'{\n "main": "./dist/lib/index.js",\n "module": "./dist/es/index.js",\n "types": "./dist/types/index.d.ts",\n "unpkg": "./dist/umd/index.js",\n};\n'})}),"\n",(0,r.jsx)(n.p,{children:"预设字符串对应的构建配置:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:"export const buildConfig = [\n {\n format: 'cjs',\n target: 'es6',\n buildType: 'bundle',\n outDir: './dist/lib',\n dts: false,\n },\n {\n format: 'esm',\n target: 'es6',\n buildType: 'bundle',\n outDir: './dist/es',\n dts: false,\n },\n {\n format: 'umd',\n target: 'es6',\n platform: 'browser',\n buildType: 'bundle',\n outDir: './dist/umd',\n dts: false,\n },\n {\n buildType: 'bundle',\n outDir: './dist/types',\n dts: {\n only: true,\n },\n },\n];\n"})}),"\n",(0,r.jsxs)(n.h2,{id:"npm-component",children:[(0,r.jsx)(n.code,{children:"npm-component"}),(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#npm-component",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["在类 ",(0,r.jsx)(n.a,{href:"https://www.npmjs.com/",target:"_blank",rel:"noopener noreferrer",children:"NPM"})," 包管理器下使用的 组件(库)通用模式。包含 ",(0,r.jsx)(n.code,{children:"esm"})," 和 ",(0,r.jsx)(n.code,{children:"cjs"})," 两种 Bundleless 产物(便于 ",(0,r.jsx)(n.em,{children:(0,r.jsx)(n.a,{href:"https://developer.mozilla.org/zh-CN/docs/Glossary/Tree_shaking",target:"_blank",rel:"noopener noreferrer",children:"Tree shaking"})})," 优化),以及包含一份类型文件。"]}),"\n",(0,r.jsx)(n.p,{children:"对于源码中包含的样式文件,产物中提供样式的编译产物和样式的源文件。"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",meta:'title="package.json"',children:'{\n "main": "./dist/lib/index.js", // bundleless type\n "module": "./dist/es/index.js", // bundleless type\n "types": "./dist/types/index.d.ts",\n};\n'})}),"\n",(0,r.jsx)(n.p,{children:"预设字符串对应的构建配置:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:"export const buildConfig = [\n {\n format: 'cjs',\n target: 'es6',\n buildType: 'bundleless',\n outDir: './dist/lib',\n dts: false,\n },\n {\n format: 'esm',\n target: 'es6',\n buildType: 'bundleless',\n outDir: './dist/es',\n dts: false,\n },\n {\n buildType: 'bundleless',\n outDir: './dist/types',\n dts: {\n only: true,\n },\n },\n];\n"})}),"\n",(0,r.jsxs)(n.h2,{id:"npm-component-with-umd",children:[(0,r.jsx)(n.code,{children:"npm-component-with-umd"}),(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#npm-component-with-umd",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["在类 ",(0,r.jsx)(n.a,{href:"https://www.npmjs.com/",target:"_blank",rel:"noopener noreferrer",children:"NPM"})," 包管理器下使用的组件(库),同时支持类 ",(0,r.jsx)(n.a,{href:"https://unpkg.com/",target:"_blank",rel:"noopener noreferrer",children:"unpkg"})," 的模式。 在预设 ",(0,r.jsx)(n.code,{children:"'npm-component'"})," 的基础上,额外提供 ",(0,r.jsx)(n.code,{children:"umd"})," 产物。"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",meta:'title="package.json"',children:'{\n "main": "./dist/lib/index.js", // bundleless type\n "module": "./dist/es/index.js", // bundleless type\n "types": "./dist/types/index.d.ts",\n "unpkg": "./dist/umd/index.js",\n};\n'})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:"export const buildConfig = [\n {\n format: 'cjs',\n target: 'es6',\n buildType: 'bundleless',\n outDir: './dist/lib',\n dts: false,\n },\n {\n format: 'esm',\n target: 'es6',\n buildType: 'bundleless',\n outDir: './dist/es',\n dts: false,\n },\n {\n format: 'umd',\n target: 'es6',\n platform: 'browser',\n buildType: 'bundle',\n outDir: './dist/umd',\n dts: false,\n },\n {\n buildType: 'bundleless',\n outDir: './dist/types',\n dts: {\n only: true,\n },\n },\n];\n"})}),"\n",(0,r.jsxs)(n.h2,{id:"npm-library-es5esnext",children:[(0,r.jsx)(n.code,{children:"npm-library-{es5...esnext}"}),(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#npm-library-es5esnext",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["当想要使用支持其他 ECMAScript 版本的 ",(0,r.jsx)(n.code,{children:"buildPreset"})," 预设的时候,可以直接在 ",(0,r.jsx)(n.code,{children:"'npm-library'"}),"、",(0,r.jsx)(n.code,{children:"'npm-library-with-umd'"}),"、",(0,r.jsx)(n.code,{children:"'npm-component'"}),"、",(0,r.jsx)(n.code,{children:"'npm-component-with-umd'"})," 这些预设值后面增加想要支持的版本。"]}),"\n",(0,r.jsxs)(n.p,{children:["例如希望 ",(0,r.jsx)(n.code,{children:"'npm-library'"})," 预设支持 ",(0,r.jsx)(n.code,{children:"'es2017'"}),",则可以按照如下方式配置:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",meta:'title="modern.config.ts"',children:"import { defineConfig } from '@modern-js/module-tools';\n\nexport default defineConfig({\n buildPreset: 'npm-library-es2017',\n});\n"})}),"\n",(0,r.jsxs)(n.h2,{id:"string--function",children:["string / function",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#string--function",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["buildPreset 除了支持基本的字符串形式,还支持函数形式,可以通过 ",(0,r.jsx)(n.code,{children:"preset"})," 或者 ",(0,r.jsx)(n.code,{children:"extendPreset"})," 参数获取我们提供的预设值,然后进行修改。"]}),"\n",(0,r.jsxs)(n.p,{children:["以下是两个分别使用 ",(0,r.jsx)(n.code,{children:"preset"})," 和 ",(0,r.jsx)(n.code,{children:"extendPreset"})," 的例子:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",meta:'title="modern.config.ts"',children:"import { defineConfig } from '@modern-js/module-tools';\n\nexport default defineConfig({\n buildPreset({ preset }) {\n const { NPM_LIBRARY } = preset;\n return NPM_LIBRARY.map(config => {\n config.define = {\n VERSION: '1.0.1',\n };\n return config;\n });\n },\n});\n"})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"extendPreset"})," 里会使用 lodash.merge 进行配置合并"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",meta:'title="modern.config.ts"',children:"import { defineConfig } from '@modern-js/module-tools';\n\nexport default defineConfig({\n buildPreset({ extendPreset }) {\n return extendPreset('npm-library', {\n define: {\n VERSION: '1.0.1',\n },\n });\n },\n});\n"})})]})}function t(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,d.ah)(),e.components);return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(i,{...e})}):i(e)}let l=t;t.__RSPRESS_PAGE_META={},t.__RSPRESS_PAGE_META["zh%2Fapi%2Fconfig%2Fbuild-preset.mdx"]={toc:[{text:"`npm-library`",id:"npm-library",depth:2},{text:"`npm-library-with-umd`",id:"npm-library-with-umd",depth:2},{text:"`npm-component`",id:"npm-component",depth:2},{text:"`npm-component-with-umd`",id:"npm-component-with-umd",depth:2},{text:"`npm-library-{es5...esnext}`",id:"npm-library-es5esnext",depth:2},{text:"string / function",id:"string--function",depth:2}],title:"buildPreset",frontmatter:{sidebar_position:2}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_modern_js_module_tools_docs=self.webpackChunk_modern_js_module_tools_docs||[]).push([["9611"],{6824:function(e,n,o){o.r(n),o.d(n,{default:function(){return c}});var r=o(8093),s=o(5878);function i(e){let n=Object.assign({h1:"h1",a:"a",p:"p",h2:"h2",div:"div",strong:"strong",h3:"h3",ul:"ul",li:"li",code:"code",pre:"pre",img:"img",h4:"h4"},(0,s.ah)(),e.components);return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.h1,{id:"dev",children:["dev",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#dev",children:"#"})]}),"\n",(0,r.jsx)(n.p,{children:"This section describes all configuration of Modern.js Module related to debugging tools."}),"\n",(0,r.jsxs)(n.h2,{id:"storybook",children:["storybook",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#storybook",children:"#"})]}),"\n",(0,r.jsxs)(n.div,{className:"rspress-directive warning",children:[(0,r.jsx)(n.div,{className:"rspress-directive-title",children:"WARNING"}),(0,r.jsx)(n.div,{className:"rspress-directive-content",children:(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Deprecated"}),": This configuration is deprecated and only applicable to Storybook V6. Please see ",(0,r.jsx)(n.a,{href:"/guide/basic/using-storybook",children:"使用Storybook"})," to get more info.\n"]})})]}),"\n",(0,r.jsxs)(n.h3,{id:"storybookwebpack",children:["storybook.webpack",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#storybookwebpack",children:"#"})]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Type"}),": ",(0,r.jsx)(n.code,{children:"object | Function | undefined"})]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Default"}),": ",(0,r.jsx)(n.code,{children:"undefined"})]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"export default {\n dev: {\n storybook: {\n webpack(config) {\n return config;\n },\n },\n },\n};\n"})}),"\n",(0,r.jsxs)(n.p,{children:["You can modify the webpack configuration of the Storybook Preview-iframe via ",(0,r.jsx)(n.code,{children:"dev.storybook.webpack"}),". The usage can be found in the ",(0,r.jsx)(n.a,{href:"https://modernjs.dev/builder/en/api/config-tools.html#toolswebpack",target:"_blank",rel:"noopener noreferrer",children:(0,r.jsx)(n.code,{children:"tools.webpack"})})," configuration of Modern.js."]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{src:"https://storybook.js.org/71522ac365feaf3338d7c242e53378f6/manager-preview.png",alt:"Storybook"})}),"\n",(0,r.jsxs)(n.h4,{id:"configure-manager-app",children:["Configure Manager App",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#configure-manager-app",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["For the webpack configuration of the Storybook Manager app section, you can configure it by adding the ",(0,r.jsx)(n.code,{children:"./config/storybook/main.js"})," file to configure it."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:"// ./config/storybook/main.js\n\nmodule.exports = {\n // it controls the Storybook manager app\n managerWebpack: async (config, options) => {\n // update config here\n return config;\n },\n};\n"})}),"\n",(0,r.jsxs)(n.h3,{id:"storybookwebpackchain",children:["storybook.webpackChain",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#storybookwebpackchain",children:"#"})]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Type"}),": ",(0,r.jsx)(n.code,{children:"Function | undefined"})]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Default"}),": ",(0,r.jsx)(n.code,{children:"undefined"})]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"export default {\n dev: {\n storybook: {\n webpackChain(chain) {\n return chain;\n },\n },\n },\n};\n"})}),"\n",(0,r.jsxs)(n.p,{children:["You can modify the webpack configuration of the Storybook Preview-iframe via ",(0,r.jsx)(n.code,{children:"dev.storybook.webpackChain"}),". You can refer to Modern.js's ",(0,r.jsx)(n.a,{href:"https://modernjs.dev/builder/en/api/config-tools.html#toolswebpackchain",target:"_blank",rel:"noopener noreferrer",children:(0,r.jsx)(n.code,{children:"tools.webpackChain"})})," configuration for how to use it."]})]})}function a(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,s.ah)(),e.components);return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(i,{...e})}):i(e)}let c=a;a.__RSPRESS_PAGE_META={},a.__RSPRESS_PAGE_META["en%2Fapi%2Fconfig%2Fdev.md"]={toc:[{text:"storybook",id:"storybook",depth:2},{text:"storybook.webpack",id:"storybookwebpack",depth:3},{text:"Configure Manager App",id:"configure-manager-app",depth:4},{text:"storybook.webpackChain",id:"storybookwebpackchain",depth:3}],title:"dev",frontmatter:{sidebar_position:3}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_modern_js_module_tools_docs=self.webpackChunk_modern_js_module_tools_docs||[]).push([["964"],{1808:function(e,t,n){n.r(t),n.d(t,{default:function(){return u}});var o=n(8093),s=n(5878);function _(e){return(0,o.jsx)(o.Fragment,{})}function r(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:t}=Object.assign({},(0,s.ah)(),e.components);return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(_,{...e})}):_(e)}let u=r;r.__RSPRESS_PAGE_META={},r.__RSPRESS_PAGE_META["zh%2Fcomponents%2Fpublish-emo.mdx"]={toc:[],title:"",frontmatter:{}}}}]);
|