欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

webpack多页面方案

程序员文章站 2022-07-12 19:30:12
...

上一篇总结了webpack的配置,其实配置还是相对容易的,因为只要根据需要照搬选项就好了,但是只写配置项那最终打包出来的结果就是一个html和一个js,如果页面多了那肯定是不行的,所以就需要想办法拆分代码,我所知道的拆分代码方式大概有2种:1.使用react-loadable + import();2.entry的对象写法和html-webpack-plugin的chunks选项;

参考文章比较多,没怎么记录

方案1

react-loadable + import()
这个方案需要@babel/plugin-syntax-dynamic-import的支持,记得修改babelrc。一般用这个方案的话是要用react-router来写一个单页应用,模板加载一个入口js,入口js里把页面路由写好,每个页面作为一个组件,然后写一个类似这样的结构

import Loadable from 'react-loadable';

const routeArr = [
  {
    path: '/page1',
    component: Loadable({
      loader: () =>
        import(
          /* webpackChunkName: "page1" */
          './page1'
        ),
      loading: <div>loading...</div>
    })
  },
  {
    path: '/page2',
    component: Loadable({
      loader: () =>
        import(
          /* webpackChunkName: "page2" */
          './page2'
        ),
      loading: <div>loading...</div>
    })
  }
]

// 其他部分省略了
render() {
    return (
      <Switch> // 用Switch而不是Router可以保证只匹配到一个路径
        {routeArr.map((v, k) => {
          return <Route key={k} path={`/${v.path}`} component={v.component} />;
        })}
      </Switch>
    );
  }

这个方案的问题在于,/* webpackChunkName: "page2" */这个注释,这个注释不加,动态import是不生效的,即使生效,也不能通过写一个循环来把所有的页面组件都循环import,也就是说,每添加一个页面组件,就要自己往routeArr里加一段代码,当然可以通过别的方式来生成这个routeArr,比如写文件方式,根本问题就是routeArr要以硬编码形式存在,而不能是这样的

const routeArr = ['page1', 'page2'].map((v, k)=>{
    return {
    path: `/${v}`,
    component: Loadable({
      loader: () =>
        import(`./${v}`),
      loading: <div>loading...</div>
    })
  };
})

这个方案的优点在于,1.不需要多个html模板,是个标准的单页应用;2.不需要多个html-webpack-plugin实例;3.工程路径可以随意,只要写到路由数组里的时候自己确定是对的就可以,不需要统一,但是作为一个工程当然是统一为好;4.写一些页面共有的组件,比如菜单,顶部导航等比较简单

方案2

webpack的入口配置这样写

entry: {
    page1:"./src/page1.js",
    page2:"./src/page2.js"
},
output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name]_[contenthash].js' // 这里如果用hash,每个文件的hash是一样的,所以要用内容hash
}

html-webpack-plugin插件这样来写

const HtmlWebpackPlugin = require("html-webpack-plugin");

plugins: [
    new HtmlWebpackPlugin({
        filename: "page1.html", 
        template: "./src/page1.html",}),
        chunks: ["page1"]
    }),
    new HtmlWebpackPlugin({
        filename: "page2.html",
        template: "./src/page2.html",}),
        chunks: ["page2"]
    })
]

注意创建HtmlWebpackPlugin实例时的chunks选项,这个选项如果不写,默认会把entry里生成的所有文件全部注入到每个HtmlWebpackPlugin实例里去,为了出这个坑我看了好多篇文章

这个方案的优点在于,不用每次手写添加的页面的名称和路由(对比方案1),只要按照约定的工程目录创建页面,就可以通过遍历目录生成入口和HtmlWebpackPlugin实例来打包,缺点是页面多的情况下HtmlWebpackPlugin实例也很多,应该会影响性能,并且如果要写一些页面上都有的组件(比如菜单和导航),就要在每个页面里自己引用

方案3

如果觉得多个html-webpack-plugin实例的方式不靠谱,可以把方案2改改,还是配多个entry,工程目录也一样,然后自己写一个路由,根据当前加载的url来判断加载哪个js,这样其实就和方案1很类似了,这个路由写在服务端会比较好,可以提前设置好js的链接,也可以实现页面权限之类的需求