资讯专栏INFORMATION COLUMN

create-react-app 修改为多入口编译

LancerComet / 1164人阅读

摘要:修改为多入口编译参考了这篇文章需求和出发点我们会有较多的小的单页应用,主要是一些简单的页面和活动之类。甚至输入显然不存在的,也显示为的内容。

create-react-app 修改为多入口编译

date: 2018.07.31

参考了这篇文章

需求和出发点

我们会有较多的小的单页应用,主要是一些简单的页面和活动之类。这些页面相互之间没有交集,但是会有一些可以共用的代码,资源、接口、组件啥的。

对此,我们想到了两种解决方案:

react-router 路由方案;

同一个项目的多入口编译;

针对我们的业务需求,其实 react-router 方案会有两个小问题:

单个活动的修改,其实需要编译整个项目;

若是不做编译优化,整个项目的包会比较大,但其实没必要,当然这个可以通过 react-router 的按需加载来解决;

权衡之下,我们还是选择了第二个方案——改造项目成为多入口编译。

文件结构设计

改进后,整个项目的结构大体如下:

- project
    - build
    - config
    - public
    - scripts
    - src
        - api
        - component
        - site
            - site1
                - index.html
                - index.js
                - ...
            - site2
                - index.html
                - index.js
                - ...
    - package.json

site 文件夹下的所有文件夹都是一个独立的项目,项目通用的代码、资源被抽离到更外层的文件夹内,如 api、component 等,文件夹内都会有自己的 index.html 和 index.js,这会作为该项目的 html 模板和入口文件。下面,我们看下是如何修改编译过程的。

修改入口和出口

编译需要指定编译的入口和输出的位置,在 create-react-app 本来生成的 code 中,只有单入口和单出口,但是其实 webpack 是支持多入口、多出口的。

入口修改

create-react-app 命令生成的 config 文件夹中,有个 paths.js 文件,这里面 export 了比较常用的路径。在这里,我对 src/site 文件夹内的文件夹进行了遍历,生成为对象。具体代码如下:

// all site paths
function allSitePath(source) {
  const { lstatSync, readdirSync } = fs
  const { join } = path
  const result = {}
  const isDirectory = source => lstatSync(source).isDirectory()
  readdirSync(source).map(name => {
    let path = join(resolveApp(source), name)
    if (isDirectory(path)) result[name] = path
  })
  return result
}

module.exports = {
  ...
  allSites: allSitePath("src/site"),
}

在 webpack.config.dev.js / webpack.config.prod.js 中找到 module.exports 的 entry 属性,将其修改为:

// 动态生成 entry
const entry = {}
Object.keys(paths.allSites).forEach(item => {
  entry[item] = [
    require.resolve("./polyfills"),
    require.resolve("react-dev-utils/webpackHotDevClient"),
    require.resolve("react-error-overlay"),
    paths.allSites[item]
  ]
})

module.exports = {
  ...
  entry: entry,
  ...
}
出口修改

出口的修改分为两部分,一部分是 module.exports 的 output,添加 name 以使静态资源区分不同项目:

module.exports = {
  ...
  output: {
    path: paths.appBuild,
    pathinfo: true,
    filename: "static/js/[name].bundle.js",
    chunkFilename: "static/js/[name].chunk.js",
    publicPath: publicPath,
    devtoolModuleFilenameTemplate: info =>
      path.resolve(info.absoluteResourcePath).replace(//g, "/"),
  },
  ...
} 

另一部分是 plugin 的修改,webpack 中,每个 HTML 文件的输出,其实是一个 HtmlWebpackPlugin,我们需要添加多个 HtmlWebpackPlugin,以求生成多个 HTML:

// 动态生成 plugins
const plugins = []
Object.keys(paths.allSites).forEach(item => {
  plugins.push(new HtmlWebpackPlugin({
    inject: true,
    chunks: [item],
    template: `${paths.allSites[item]}/index.html`,
    filename: `${item}/index.html`,
  }))
})

module.exports = {
  ...
  plugins: [
    ...
  ].concat(plugins),    
  ...
}
修改 webpack Dev Server 配置

上述配置做完后,理论就可以打包出多入口的版本;但使用npm start启动后,发现无论输入/index.html还是/admin.html,好像都是和原来/index.html显示一样的内容。甚至输入显然不存在的/xxxx.html,也显示为/index.html的内容。

这里,我们还需要修改 /config/webpackDevServer.config.js,做一些额外配置。

const rewrites = []
Object.keys(paths.allSites).forEach(item => {
  rewrites.push({
    from: new RegExp(`^/${item}/`, "i"),
    to: `/${item}/index.html`,
  })
})

...

module.exports = function(proxy, allowedHost) {
  return {
    ...
    historyApiFallback: {
      // Paths with dots should still use the history fallback.
      // See https://github.com/facebookincubator/create-react-app/issues/387.
      disableDotRule: true,
      // 指明哪些路径映射到哪个html
      rewrites: rewrites,
    },
    ...
  };
};

OK,到这里,整个改造就完成了。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/96471.html

相关文章

  • react 应用多入口 配置 && 实践总结

    摘要:如果不配置,则将所有的文件都注入。指明生成的路径,如果不配置就是。配置了新的,避免与第一个入口相互覆盖。甚至输入显然不存在的,也显示为的内容。这种现象,初步判断是服务器把所有请求重定向到了。至此,环境的多入口问题就解决了。前端根据自行配置。 背景 还是之前的那个项目,做完国际化没多久,还没来得及划水, 又有新的活了 -- 移动端的兼容。 考虑到后期的复杂度, 需要做两套资源。 具体的目...

    Sike 评论0 收藏0
  • react 应用多入口 配置 && 实践总结

    摘要:如果不配置,则将所有的文件都注入。指明生成的路径,如果不配置就是。配置了新的,避免与第一个入口相互覆盖。甚至输入显然不存在的,也显示为的内容。这种现象,初步判断是服务器把所有请求重定向到了。至此,环境的多入口问题就解决了。前端根据自行配置。 背景 还是之前的那个项目,做完国际化没多久,还没来得及划水, 又有新的活了 -- 移动端的兼容。 考虑到后期的复杂度, 需要做两套资源。 具体的目...

    curried 评论0 收藏0
  • react+express项目

    摘要:暴露所有内建配置,项目下会新增或对部分配置文件进行修改。开发环境开发时,前端项目和后端项目运行时端口端口不同,存在跨域问题。项目目录结构优化项目目录结构优化开发目录主要是目录,因此需要修改的目录主要是目录。 1 开发环境准备(windows) 1.1 安装nodejs和npm 1) 下载nodejs安装包:http://nodejs.org/en/download/ nodejs安...

    Luosunce 评论0 收藏0
  • 初探react技术栈(一)

    摘要:相信用的同学也不少找到函数在其中中添加启用编译。。。react 最近已经开始使用react技术栈了,从头开始搭建项目,有必要的记录一下配置的过程以及项目分层的思路,这次后台项目采用的主要采用react-create-app脚手架以及Ant DesignUI 以及多语言react-intl create-react-app 这是官方维护的脚手架应用 我们一般也采用这个 $ npm or c...

    刘玉平 评论0 收藏0
  • 初探React技术栈(一)

    react 最近已经开始使用react技术栈了,从头开始搭建项目,有必要的记录一下配置的过程以及项目分层的思路,这次后台项目采用的主要采用react-create-app脚手架以及Ant DesignUI 以及多语言react-intl create-react-app 这是官方维护的脚手架应用 我们一般也采用这个 $ npm or cnpm $ npm install create-react...

    neroneroffy 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<