diff --git a/docs/config/README.md b/docs/config/README.md index 5411e09d32..55f9e85049 100644 --- a/docs/config/README.md +++ b/docs/config/README.md @@ -121,7 +121,11 @@ Deprecated since Vue CLI 3.3, please use [`publicPath`](#publicPath) instead. title: 'Index Page', // chunks to include on this page, by default includes // extracted common chunks and vendor chunks. - chunks: ['chunk-vendors', 'chunk-common', 'index'] + chunks: ['chunk-vendors', 'chunk-common', 'index'], + // devServer.historyApiFallback.rewrites + // We can set advanced path regex when serve + // Notice: This option doesn't effect production. + from: /^\/m(\/.*)?$/ }, // when using the entry-only string format, // template is inferred to be `public/subpage.html` diff --git a/docs/zh/config/README.md b/docs/zh/config/README.md index 1c9f3bba01..bc23c57e62 100644 --- a/docs/zh/config/README.md +++ b/docs/zh/config/README.md @@ -103,7 +103,7 @@ module.exports = { 在 multi-page 模式下构建应用。每个“page”应该有一个对应的 JavaScript 入口文件。其值应该是一个对象,对象的 key 是入口的名字,value 是: - - 一个指定了 `entry`, `template`, `filename`, `title` 和 `chunks` 的对象 (除了 `entry` 之外都是可选的); + - 一个指定了 `entry`, `template`, `filename`, `title`, `from` 和 `chunks` 的对象 (除了 `entry` 之外都是可选的); - 或一个指定其 `entry` 的字符串。 ``` js @@ -121,7 +121,11 @@ module.exports = { title: 'Index Page', // 在这个页面中包含的块,默认情况下会包含 // 提取出来的通用 chunk 和 vendor chunk。 - chunks: ['chunk-vendors', 'chunk-common', 'index'] + chunks: ['chunk-vendors', 'chunk-common', 'index'], + // devServer.historyApiFallback.rewrites + // 当使用开发服务器时,能进阶控制匹配路径 + // 注意: 这个选项不会影响生产环境 + from: /^\/m(\/.*)?$/ }, // 当使用只有入口的字符串格式时, // 模板会被推导为 `public/subpage.html` diff --git a/packages/@vue/cli-service/__tests__/multiPage.spec.js b/packages/@vue/cli-service/__tests__/multiPage.spec.js index c85e2c4f65..e2ea13ca32 100644 --- a/packages/@vue/cli-service/__tests__/multiPage.spec.js +++ b/packages/@vue/cli-service/__tests__/multiPage.spec.js @@ -20,6 +20,10 @@ async function makeProjectMultiPage (project) { entry: 'src/main.js', template: 'public/baz.html', filename: 'qux.html' + }, + m: { + from: /^\\/m(\\/.*)?$/, + entry: 'src/mobile.js', } }, chainWebpack: config => { @@ -53,6 +57,13 @@ async function makeProjectMultiPage (project) { render: h => h('h1', 'FooBar') }) `) + await project.write('src/mobile.js', ` + import Vue from 'vue' + new Vue({ + el: '#app', + render: h => h('h1', 'Mobile') + }) + `) const app = await project.read('src/App.vue') await project.write('src/App.vue', app.replace( `import HelloWorld from './components/HelloWorld.vue'`, @@ -84,6 +95,18 @@ test('serve w/ multi page', async () => { await page.goto(`${url}foobar`) expect(await helpers.getText('h1')).toMatch(`FooBar`) + + await page.goto(`${url}m`) + expect(await helpers.getText('h1')).toMatch(`Mobile`) + + await page.goto(`${url}m/`) + expect(await helpers.getText('h1')).toMatch(`Mobile`) + + await page.goto(`${url}m/oao`) + expect(await helpers.getText('h1')).toMatch(`Mobile`) + + await page.goto(`${url}message`) + expect(await helpers.getText('h1')).not.toMatch(`Mobile`) } ) }) @@ -193,6 +216,9 @@ test('build w/ multi page', async () => { await page.goto(`${url}bar.html`) expect(await getH1Text()).toMatch('Welcome to Your Vue.js App') + + await page.goto(`${url}m.html`) + expect(await getH1Text()).toMatch('Mobile') }) afterAll(async () => { diff --git a/packages/@vue/cli-service/lib/commands/serve.js b/packages/@vue/cli-service/lib/commands/serve.js index 8c97ef02af..68d1a6380d 100644 --- a/packages/@vue/cli-service/lib/commands/serve.js +++ b/packages/@vue/cli-service/lib/commands/serve.js @@ -353,7 +353,7 @@ function genHistoryApiFallbackRewrites (baseUrl, pages = {}) { // eg. 'page11' should appear in front of 'page1' .sort((a, b) => b.length - a.length) .map(name => ({ - from: new RegExp(`^/${name}`), + from: pages[name].from || new RegExp(`^/${name}`), to: path.posix.join(baseUrl, pages[name].filename || `${name}.html`) })) return [