From f0f22e652a0bc73ec6d92b0bdfd6a55e6556fc2a Mon Sep 17 00:00:00 2001 From: Miaolegemie <1942037006@qq.com> Date: Sun, 10 Mar 2019 01:34:55 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AF=B9=E7=94=9F=E6=88=90?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=AD=90=E7=9B=AE=E5=BD=95=E7=9A=84=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 11 +- src/index.ts | 27 ++++- src/schema.test.ts | 6 + src/schema.ts | 3 + test/fixtures/deep-entry/.umirc.js | 8 ++ .../deep-entry/expected/deep/index.js | 101 +++++++++++++++++ test/fixtures/deep-entry/expected/index.js | 103 ++++++++++++++++++ .../deep-entry/pages/__test__/index.js | 1 + test/fixtures/deep-entry/pages/deep/index.js | 1 + test/fixtures/deep-entry/pages/index.js | 1 + 10 files changed, 256 insertions(+), 6 deletions(-) create mode 100644 test/fixtures/deep-entry/.umirc.js create mode 100644 test/fixtures/deep-entry/expected/deep/index.js create mode 100644 test/fixtures/deep-entry/expected/index.js create mode 100644 test/fixtures/deep-entry/pages/__test__/index.js create mode 100644 test/fixtures/deep-entry/pages/deep/index.js create mode 100644 test/fixtures/deep-entry/pages/index.js diff --git a/README.md b/README.md index 9e4eec8..3399ab8 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ MPA(multiple-page application) plugin for umi. - ✔︎ 禁用 umi 内置的路由功能 - ✔︎ 禁用 umi 默认生成的 entry 配置 - ✔︎ 支持通过 targets 配置的补丁方案,配 `BABEL_POLYFILL=none` 则不打补丁 -- ✔︎ 支持自动查找 `src/pages` 下的 js 文件为 entry +- ✔︎ 支持多级目录自动查找 `src/pages` 下的 js 文件为 entry - ✔︎ import 的 html 文件会被生成到 dist 目录下 - ✔︎ Hot Module Replacement - ✔︎ 通过 `splitChunks` 配置提取公共部分 @@ -102,6 +102,15 @@ entry 的额外配置项目前支持: 可以用 `[name]`、`[path]`、`[hash]` 和 `[ext]`,详见 https://github.com/webpack-contrib/file-loader 。 +### deepPageEntry + +在自动查找 `src/pages` 下的 js 或 ts 文件为 entry 时,是否进入子目录查找 + +- Type: `Boolean` +- Default: `false` + +注:会跳过以 `__` 或 `.` 开头的目录 + ### splitChunks 配置 webpack 的 splitChunks,用于提取 common 或 vendors 等。 diff --git a/src/index.ts b/src/index.ts index b78bf3e..8aa51ed 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,7 @@ import { IApi } from 'umi-plugin-types'; -import { existsSync, readdirSync } from 'fs'; +import { existsSync, readdirSync, lstatSync } from 'fs'; import { join, extname, basename, dirname } from 'path'; -import { cloneDeep, isPlainObject } from 'lodash'; +import { cloneDeep, isPlainObject, flattenDeep } from 'lodash'; import AJV from 'ajv'; import schema from './schema'; @@ -14,6 +14,7 @@ const semver = require('semver'); interface IOption { entry?: object, htmlName?: string, + deepPageEntry?: boolean, splitChunks?: object | boolean, html?: { template?: string, @@ -29,6 +30,18 @@ interface IEntryConfig { context?: object, } +function getFiles(absPath: string, path: string, files: string[]) { + return files.map(f => { + const lstat = lstatSync(join(absPath, path, f)); + if(f.charAt(0) !== '.' && !f.startsWith('__') && lstat.isDirectory()) { + const subDirFiles = readdirSync(join(absPath, path, f)); + return getFiles(absPath, join(path, f), subDirFiles); + } else { + return join(path, f); + } + }) +} + export default function(api: IApi, options = {} as IOption) { const { log, paths } = api; @@ -86,10 +99,14 @@ ${errors.join('\n')} log.info( `[umi-plugin-mpa] options.entry is null, find files in pages for entry`, ); - webpackConfig.entry = readdirSync(paths.absPagesPath) - .filter(f => f.charAt(0) !== '.' && /\.(j|t)sx?$/.test(extname(f))) + // 是否进入子目录生成路由 + const allFiles = options.deepPageEntry + ? flattenDeep(getFiles(paths.absPagesPath, '', readdirSync(paths.absPagesPath))) + : readdirSync(paths.absPagesPath); + webpackConfig.entry = (allFiles as string[]) + .filter(f => basename(f).charAt(0) !== '.' && /\.(j|t)sx?$/.test(extname(f))) .reduce((memo, f) => { - const name = basename(f, extname(f)); + const name = f.replace(/\.(j|t)sx?$/, ''); memo[name] = [join(paths.absPagesPath, f)]; return memo; }, {}); diff --git a/src/schema.test.ts b/src/schema.test.ts index 7bc9351..9c09d82 100644 --- a/src/schema.test.ts +++ b/src/schema.test.ts @@ -16,6 +16,12 @@ describe('schema', () => { })).toEqual(true); }); + it('deepPageEntry', () => { + expect(ajv.validate(schema, { + deepPageEntry: true, + })).toEqual(true); + }); + it('splitChunks', () => { // boolean expect(ajv.validate(schema, { diff --git a/src/schema.ts b/src/schema.ts index 8b62ac1..afbc9e3 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -10,6 +10,9 @@ export default { type: 'string', minLength: 1, }, + deepPageEntry: { + type: 'boolean', + }, splitChunks: { anyOf: [ { type: 'boolean' }, diff --git a/test/fixtures/deep-entry/.umirc.js b/test/fixtures/deep-entry/.umirc.js new file mode 100644 index 0000000..f13dc0c --- /dev/null +++ b/test/fixtures/deep-entry/.umirc.js @@ -0,0 +1,8 @@ + +export default { + plugins: [ + ['../../../dist/index', { + deepPageEntry: true, + }], + ], +}; diff --git a/test/fixtures/deep-entry/expected/deep/index.js b/test/fixtures/deep-entry/expected/deep/index.js new file mode 100644 index 0000000..b2f7662 --- /dev/null +++ b/test/fixtures/deep-entry/expected/deep/index.js @@ -0,0 +1,101 @@ +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = "/"; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = __webpack_require__(1); + + +/***/ }), +/* 1 */ +/***/ (function(module, exports) { + +alert('deep'); + +/***/ }) +/******/ ]); \ No newline at end of file diff --git a/test/fixtures/deep-entry/expected/index.js b/test/fixtures/deep-entry/expected/index.js new file mode 100644 index 0000000..7ee89dd --- /dev/null +++ b/test/fixtures/deep-entry/expected/index.js @@ -0,0 +1,103 @@ +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = "/"; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 2); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */, +/* 1 */, +/* 2 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = __webpack_require__(3); + + +/***/ }), +/* 3 */ +/***/ (function(module, exports) { + +alert('foooo'); + +/***/ }) +/******/ ]); \ No newline at end of file diff --git a/test/fixtures/deep-entry/pages/__test__/index.js b/test/fixtures/deep-entry/pages/__test__/index.js new file mode 100644 index 0000000..ad52d8b --- /dev/null +++ b/test/fixtures/deep-entry/pages/__test__/index.js @@ -0,0 +1 @@ +alert('err'); diff --git a/test/fixtures/deep-entry/pages/deep/index.js b/test/fixtures/deep-entry/pages/deep/index.js new file mode 100644 index 0000000..b596a90 --- /dev/null +++ b/test/fixtures/deep-entry/pages/deep/index.js @@ -0,0 +1 @@ +alert('deep'); diff --git a/test/fixtures/deep-entry/pages/index.js b/test/fixtures/deep-entry/pages/index.js new file mode 100644 index 0000000..1e61834 --- /dev/null +++ b/test/fixtures/deep-entry/pages/index.js @@ -0,0 +1 @@ +alert('foooo');