Giter Site home page Giter Site logo

blog's Introduction

blog

Hello
我是一个前端
我会在这里记录下我工作中碰到的问题和解决这些问题的过程

blog's People

Contributors

jason3925 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

blog's Issues

记录平时开发中遇到的问题(长期更新)

[TOC]

关于npm中的参数传递

我在使用package.jsonscripts命令的时候遇到了一个参数传递问题
npm run build -type all这条命令中的--type all参数无法继承到npm run build命令具体执行的那条命令上去

解决办法

npm run build -- -type all

npm命令中,--后的内容会继承到真实的命令中去

关于写命令配置参数

这个其实比较自由,实现的方法很多,就像一个网站,你可以使用jquery、php、jsp、react、vue、ng中的任何一种来实现一样,用你觉得对的语法就好,当然,我这里还是要推荐下我觉得挺好的语法

const argv = yargs.option('t', {
  alias: 'type',
  demand: true,
  describe: '类型',
  type: 'string'
}).argv;

yargs是个很强大的库,推荐给大家 链接

可能会用到的库

最近写个工具,用到了一些库,记录一下,同时也推荐给大家

const rimraf = require('rimraf');
const copydir = require('copy-dir');
const chalk = require('chalk');

copy-dir-参考
rimraf-参考
chalk-参考

rimraf 用于清空文件夹相当于rm -rf,所以用起来小心一点,主要用于编译等操作之前清空目标文件

  rimraf.sync('./public/*');

copydir复制文件夹,支持同步异步操作`

  copydir.sync('a', 'b');
// a 源文件夹 b目标文件夹

chalk可以在控制台输出不同颜色的信息,用于写工具提醒的提醒信息,告别单调的console.log('xxx')

console.log(chalk.red('hello world'));

关于Koa

记录自己在使用koa的时候遇到的问题和解决办法

文件上传 跨域

工作中有个需求需要自己实现一个文件上传来测试React的一个图片上传组件

参考资料:
官方关于文件上传的demo
官方关于跨域的解决方案

实现方式就是在官方文件上传的基础上修改几行代码实现跨域文件上传

官方demo中文件上传后是直接跳转了,这里我修改了返回json格式的响应内容,可把文件名放进去实现前端暂时上传成功的图片

  // const stream = fs.createWriteStream(os.tmpdir(), Math.random().toString()));
  const stream = fs.createWriteStream(path.join(`${__dirname}/public/tmp/`, file.name));
  reader.pipe(stream);
  console.log('uploading %s -> %s', file.name, stream.path);

  // ctx.redirect('/');
  ctx.response.body = { code: 0, filePath: `public/tmp/${file.name}` };

添加跨域的支持

添加在顶部即可

const cors = require('@koa/cors');
app.use(cors());

关于dva1.x升级到2.x

dva 1.x => 2.x

记录自己在升级dva到2.x中遇到的问题,如果发现写的不对的地方请不要笑,及时沟通,新手司机上路 ^_^

参考资料

问题一:location.query

由于history版本变动,location不在包含有query对象,需要手动处理

yarn add query-string
import queryString from 'query-string';
history.listen((location) => {
const query = queryString.parse(location.search);
// console.log(query);
});

问题二 嵌套路由

R4里修改了对于嵌套路由的实现方式

// old
<Router history={history}>
  <Route path="/home" component={Container}>
    <Route path="/home/page1" component={Page1} />
    <Route path="/home/page2" component={Page2} />
  </Route>
</Router>

// new
<Router history={history}>
  <Route path="/home">
    <Container>
      <Route path="/home/page1" component={Page1} />
      <Route path="/home/page2" component={Page2} />
    </Container>
  </Route>
</Router>

// or
<Router history={history}>
  <Route path="/home" render={(props) => {
    return (
      <Container {...props}>
        <Route path="/home/page1" component={Page1} />
        <Route path="/home/page2" component={Page2} />
      </Container>
    );
  }}>
  </Route>
</Router>

最后一种写法主要用于Container组件中需要用到history location match 的情况

R4取消了关于on****钩子函数,相关实现可以在Container容器组件的生命周期里来做

关于Redirect

R4 删除了IndexRedirect,需要重定向的时候使用Redirect
Redirectto属性现在和Route的path属性一样,适配所有能适配上的路径

// error
<Switch>
  <Redirect from="/home" to="/home/page1" />
  <Route path="/home/page1" component={Page1} />
  <Route path="/home/page2" component={Page2} />
</Switch>

这样的写法会报错,因为form的值会适配到/hom/page1 /home/page2这样的所有子路径,就会出现理论上的递归跳转(会报错,不会递归,只是形容一下)
Redirect加上exact属性就好了

<Switch>
  <Redirect exact from="/home" to="/home/page1" />
  <Route path="/home/page1" component={Page1} />
  <Route path="/home/page2" component={Page2} />
</Switch>

关于Link
R4的Link拆分成了两个:Link NavLink
简单的跳转使用Link
特殊的跳转(有选中样式需求:activeClassName)使用NavLink
参考

有使用到QueueAnimLink添加动画的地方要修改为NavLink

问题三 dispatch effect 回调

在dva2.x中新增了effect返回promise的特性,现在写回调逻辑越来yue方便了

dispatch({ type: 'home/xxx' })
  .then(({ data = {} }) => {
    console.log(data);
  })
  .catch((e) => {
    // error
    console.log(e);
  });

问题四 关于使用browserHistory

在之前的版本中,我们去掉path中的#的方式是

import {browserHistory} from 'dva/router';
const app = dva({
history: browserHistory,
});

在2.x版本中需要修改为:

yarn add history
import createHistory from 'history/createBrowserHistory';
const history = createHistory();
const app = dva({
  history,
});

这里到将来可能还会有一些修改,但目前这么使用是可行的

其他相关问题

关于webpack插件html-webpack-plugin

背景:

dva之前的版本不支持文件hash,现在dva已经支持了这个功能 链接
使用方式是在.roadhog中添加hash:true的配置,默认约定在src下有一个index.ejs的模板

问题

Uncaught TypeError: Cannot read property '__reactInternalInstance$ufa3tpnn4i' of null
    at Object.getClosestInstanceFromNode (8:113)
    at findParent (
<script src="./index.js"></script>
<script type="text/javascript" src="/index.js?a6d74e09fa325aa523a2"></script>

解决方式

问题就是引入了两次index.js
方法一:删除模板中的index.js的引用
方法二:

module.exports = (webpackConfig) => {
  const htmlWebpackPlugin = new HtmlWebpackPlugin({
    filename: 'index.html',
    template: `!!html!./src/${process.env.LOCAL_DIR}/index.html`,
    hash: true,
    inject: false,
    minify: {
      collapseBooleanAttributes: true,
    },
  });
  webpackConfig.plugins.push(htmlWebpackPlugin);
  return webpackConfig;
};

webpack.config.js的关于html-webpack-plugin的配置内容里添加inject: false
参考

inject: false,会使注入失效,如果需要hash请使用方法一

关于GitHub Pages

最近开源了一个组件、文档、测试、发布解决方案,
是基于bisheng写的,在这个过程中研究了一下GitHub Pages

这里分享一篇文章

bisheng目前发布到GitHub Pages还存在一些问题,我提了个问题,可以在这里查看进度
后续看是否需要写一篇总结在这里
待续...


2018-01-08
目前问题已经解决,原来在bishengconfig中可以定义一个root节点,这个节点就是来设置路由前缀的,因为git pages上所有的目录都是xxx.github.io/xxx/这样的结构,所以需要设置一下路由的前缀。
像这样:

if (process.env.NODE_ENV) {
  bishengConfig.htmlTemplateExtraData = {
    root: '/component-factory/'
  };
  bishengConfig.root = '/component-factory/';
}

考虑到开发环境中是不需要设置htmlTemplateExtraDataroot节点的


如果使用的是create-react-app的话,就需要手动在package.json中配置homepage节点。编译过程中,程序会解析你这个配置,解析出路由前缀和资源前缀,详情参考我上边儿分享的那篇文章

零基础学习小程序(努力更新中)

小程序现在功能越来越完善,从开发的角度虽然还有很多不足,但从业务的角度还是有必要学一下的。正巧身边有朋友想一起学习,而且基本是零基础,所以想把这个学习过程记录下来,供一些新手参考。

其实最主要的是我也没玩过小程序,所以一起学习啦 ^_^

因为好朋友是零基础开始,所以会讲很多基础的东西,如果是有基础的朋友看这个可以自己选择查看相应内容
好了,让我们开始吧,我们先列一个知识地图

记录自己做的一个图片预览网站

我喜欢旅游,偏向自然风光的旅游,但我是一个程序员,到目前为止,大多数时间只能在办公室里度过,所以在我很累或者很闲的时候,我总是习惯去看看风景图片,遐想着有一天我能去那些地方旅游。

003

国内的网站都商业化比较严重,质量高又免费的比较难找,思来想去,还是自己做一个。正巧一个好朋友在学习瀑布流布局方式,然后我突发奇想说来一场比赛,看谁能更快的构建一个瀑布流网站,所以这个网站应运而生。

还是先说一下诉求,我希望做一个可以看高质量图片的网站,图片能自动更新,加载方式用瀑布流,网站整体要比较清爽、极简。好像就这么多,让我们开始吧。

因为这个网站的核心技术点是数据源跟瀑布流布局,所以这篇 blog 重点说这两个事情。

数据源

数据源的问题我找了比较久,最开始打算用 https://picsum.photos/ 这个数据源,但后来在使用过程中发现图片更新比较慢,而且如果用随机的方式的话要自己考虑去重问题,就放弃了。最后找来找去,还是选择用 https://unsplash.com/ ,主要是它的图片质量跟更新频率都很优秀,然后图片都是免费的,不会有版权问题。但伴随而来了一个新问题,图片读取速度。

桥接数据

因为 unsplash 的站点在国外,所以在国内打开会很慢,好像没有很好的解决这个问题的办法,我最终用了一个很蠢的办法,利用自己的 vps 做一个桥接。简单来说就是我在我的 vps 服务器上起了一个服务,通过这个服务器做数据流的桥接,这样图片访问速度就达到了一个可以接受的程度。核心代码如下:

app.get("/api/xxx", (req, res) => {
  request.get(req.query.path).pipe(res)
})

看起来很简单,其实它确实很简单,使用 request 这个库就能轻松实现这个过程。

瀑布流

数据问题解决后就开始解决第二个核心问题,瀑布流。

用瀑布流关键字去搜索可以很容易的搜到一些解决方案,这些解决方案中最简单的应该算是 column-count 解决方案,利用 column-count 的特性,你可以很快的实现一个瀑布流,但在实践中我发现这个方案其实是有问题的。

.demo {
  column-count: 3;
}

瀑布流的目的是在数据加载的时候用像瀑布的方式加载数据,又称砌砖布局方式,就像这样:

1  2  3
4  5  6
7  8  9

column-count 的机制确是这样:

1 (4) 7
2  5  8
3  6  9

当有新的数据后

 1  5  9
 2  6  10
 3  7  11
(4) 8

你会发现这种排版方式其实不符合我们阅读习惯。再尝试了其他几种方式后,我最终选择了一个比较笨,但比较好理解的方式 - flex 布局方式。

flex 布局方式最大的好处就是简单、方便控制,只要把展示的图片分位 N 个数组,每个数组会记录当前数组渲染后的图片高度之和,然后在每次有新的图片的时候,优先添加早高度最小的数组里去,这样就实现了瀑布流。就像这样:

const oneLine = {
  height: 100,
  photos: [1, 4],
}

const twoLine = {
  height: 180,
  photos: [2, 5, 7, 9],
}

const threeLine = {
  height: 150,
  photos: [3, 6, 8],
}

当有新的图片10的时候,通过便利当前所有数组,找出高度最小的数组,然后添加进去。然后页面上就很简单的使用 N 个 div,然后纵向排列就好了。

yang_blog_photos_001.gif

总结

看起来写的内容不是很多,其实做这个网站过程还是很曲折的,从最开始的数据源选择,到后来的瀑布流布局,都尝试了各种方法后才找到了合适的,似乎所有的事情都是这样?总要在实践中才能找到适合自己的东西。

后记

由于没有美学细胞,这个网站的样式很简陋,所以我请了一个朋友帮忙设计一下这个网站,目前还在设计中,等有结果了我把改造过程再更新到这篇 blog 里。

业务代码中,一个页面有多个模态框(不需要同时展示)的情况下,如何拆分组件?

假如一个页面有多个模态框,其中一部分长得很像,另一部分长得很像。都不能直接用ant design提供的简约版模态框,要用Modal组件。
请问这种情况下该怎么拆分页面的组件?是所有模态框放一个模态框组件里:

<div className={styles.root}
  <Header />
  <Table />
  <Footer />
  <MyModals />
</div>

还是所有模态框都放在页面里?:

<div className={styles.root}
  <Header />
  <Table />
  <Footer />
  <Modal1 />
  <Modal2 />
  <Modal3 />
</div>

在VSCode中使用自己的代码片段

代码片段可以让我们有更好的编码体验,但使用第三方代码片段总有一些自己不想要的副作用,所以我们何不自己创建一个符合自己编码习惯的代码片段库呢

001

起因

我在写 ReactJavaScript 的时候喜欢用一些代码片段(Snippets),因为这样可以让我的专注点集中在代码逻辑和业务逻辑上,而不用过多的去回忆各种语言的特效跟语法,并且这种事情往往都是重复工作。

比如最常见的语法:

002

我们在开发过程中往往需要多次敲击它来协助我们定位一些问题,虽然我没做明确的统计,但我觉得如果开发过程中这样类似的语法全部自己手写,那会浪费很多时间。

可能大多数人在这里会想到第三方代码片段库,其实我也是一样的。但我在使用了一段时间后发现,第三方库往往有一些不符合我的使用习惯的 Snippets 会影响我正常开发,比如这种情况:

003

我的意向是输入 p 标签,然后通过 tab 键来补全语法,但这些第三方库的副作用 Snippets 让我必须先按 esc 关闭这个提醒窗口后再按 tab 继续我的代码编写。

这导致我在日常编码中经常按错,耽误很多时间,对于我这种有轻度代码洁癖的人而言,这是一种煎熬,所以我一定要解决这个问题。

Snippets

VSCode 给我们提供了一个代码片段的解决方案,可以在你本地配置属于你自己的代码片段。

配置起来很简单,只需要打开 首选项-用户代码片段 就可以开始配置了,比如我们上面提到的console.log的语法,我们可以这样配置:

{
  "consoleLog": {
    "prefix": "clg",
    "body": "console.log(${1:object});",
    "description": "Displays a message in the console"
  }
}

这样配置后,你只需要输入 clg 然后 tab 就可以补全 console.log 的全部语法,并且把光标停留在 () 之间。

VSCode 还内置了一些函数跟语法来协助我们写出功能更强大的 Snippets。比如我们可以使用$1 $2来控制我们使用该 Snippets 后的光标停留位置跟顺序,我们还可以使用内置的CURRENT_DATE变量得到当前的日期等。

更多内容请在参考连接里查看。

这些特性让我们编写适合自己的 Snippets 有了更多的可能性,在日积月累中,你的编码效率就会不知不觉的越来越高效。

当然,你也可以把你自己的 Snippets 分享出去,让它成为上文中提到的第三方库,哈哈。

参考

https://code.visualstudio.com/docs/editor/userdefinedsnippets#_creating-your-own-snippets

https://code.visualstudio.com/api/language-extensions/snippet-guide

记录我的Blog构建过程

这个 Blog 我选了一个我很不熟悉的技术栈 Gatsby,这应该算是就是跳出舒适圈吧。

002

先说说我的诉求,我希望我的 Blog 可控性比较高,这样方便我做一些自己想做的事情。然后我希望它尽可能的简洁跟简单,个人有点极简主义。然后我希望 Blog 的内容使用 MarkDown 编写,最后我希望它可以自动部署,我 push 到 Github 就可以自动发布。

好吧,就这些,让我们开始吧。

基础架构

Gatsby 是一个很优秀的基于 React 的开源架构,使用它,你可以很简单很快速构建你的网站,它已经帮你做了很多事情,比如静态化页面、统一的数据获取方式等。我很久前就有学习它的计划,但一直搁置,这次我选择使用它。

使用 Gatsby 跟我使用之前的 React 架构最大的区别应该是在数据资源层上,Gatsby 有一个内置的数据层,是基于 GraphQL 的,这个数据层包含了你开发过程需要的所有资源,比如,图片、视频、JSON 数据等。GraphQL 是一种查询语言,我在几年前就开始关注,但因为使用起来需要涉及到服务端的改造(原来的理解,但现在似乎也可以独立在展示层使用),就一直停留在只会基础的使用阶段,没有深入了解,我计划会在另一篇博客中在讲讲我的理解,这里就不明细说了。

Markdown

使用 Gatsby 开发 Blog 系统,markdown 文件也是一种静态资源,我们需要使用 Gatsby 的插件把 markdown 文件加载到 Gatsby 的数据层,然后在应用就可以随意的使用了。

module.exports = {
  plugins: [
    {
      resolve: "gatsby-source-filesystem",
      options: {
        name: "content",
        path: `${__dirname}/src/content`,
      },
    },
    "gatsby-transformer-remark",
  ],
}

我们先使用 gatsby-source-filesystem 插件把我们 markdown 文件添加到系统内,然后使用 gatsby-transformer-remark 插件把刚刚添加的内容转换为我们可以使用的数据。

当你启动了 Gatsby 的开发模式,它会自同时给你启动一个 graphql 服务,可以通过http://localhost:8001/___graphql来访问。在使用了 gatsby-transformer-remark 插件后,你会发现你的数据源里多了 allMarkdownRemarkmarkdownRemark,一个是用来查询所有的 markdown 数据,一个是来获取单个 markdown 数据的详情

Gatsby 提供了很多类似生命周期的接口,你可以使用这些接口来完成你的业务,比如在我们这个场景下,我们要使用 Gatsby 的创建页面的接口,因为我的诉求是最终通过 markdown 的方式来写 blog,那么在我每次创建一个新的 markdown 文件后,都需要把这个文件转换为一个页面。

exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions
  const result = await graphql(`
    query MyQuery {
      allMarkdownRemark {
        edges {
          node {
            frontmatter {
              path
            }
          }
        }
      }
    }
  `)
  result.data.allMarkdownRemark.edges.forEach(edge => {
    const { node } = edge
    createPage({
      path: node.frontmatter.path,
      component: path.resolve(`src/templates/post.js`),
    })
  })
}

上面的代码就是使用 Gatsby 给我们提供 graphql,来查询到所有的 markdown 数据,然后通过 createPage 方法创建对应的页面,这样我们就可以通过路由来访问我们的页面了,这里需要注意,在创建页面的时候,我们还需要指定一个模板文件,每个页面的具体内容,我们需要在模板里再通过 markdownRemark 去查询,查询条件就是路由 path,如下所示:

export const pageQuery = graphql`
  query($path: String!) {
    markdownRemark(frontmatter: { path: { eq: $path } }) {
      html
      frontmatter {
        date(formatString: "YYYY MM DD")
        title
        path
      }
    }
  }
`

然后我们就可以写我们最熟悉的组件代码了

const Templates = props => {
  const { markdownRemark } = props.data
  const { html, frontmatter } = markdownRemark
  return (
    <div>
      <h1>{frontmatter.title}</h1>
      <h2>{frontmatter.date}</h2>
      <div dangerouslySetInnerHTML={{ __html: html }} />
    </div>
  )
}

自动发布

开始处理自动发布需求,虽然网上有很多类似的架构跟教程,但我觉得既然底层原理很简单,还是自己实现一个,这样比较好控制。

自动发布的核心是 Git 的 Hook 机制,在 Github 里对应的是 Settings 页面的 Webhooks 选项,可以让用户填写一个 API,在你的库发生改变的时候就自动调用里设置的 API。

然后我用 node 的 Express 在服务端运行了一个 Web 程序,通过 shelljs 这个库来执行一个写好的脚本,在脚本里做安装依赖、编译、重启 Nginx 的操作,这样看起来一个简单的自动化发布系统就做好了,虽然很简陋。

总结

到目前为止,我的需求都已经满足了,一个干净的用 Markdown 编写的可以自动发布的 Blog 系统。其实还有很多细节跟踩坑我没细说,主要是因为我不太会把控技术细节跟描述文字之间的界线,担心太多的技术内容导致阅读体验下降。

我比较喜欢兴趣式学习方式,所以我也用这种方式来学习前端技术,就像你看到的这个 Blog,因为兴趣,我在这个过程中学习了使用 Gatsby,学习了自动发布等工作中会遇到的一些技术,我很喜欢这种方式跟节奏。

开始学习umi

前言

umi 马上就要发布1.x版本,其中包含了很多现在前端的痛点解决方案,仔细分析后觉得很有必要好好学习。
后续的时间会陆续在这里更新我在学习和使用umi中遇到的问题。
相关:
官方网站
成哥的描述 强烈建议大家都去细细阅读,其中包含很多知识点

开始

ESLint

遇到的第一个问题是vscode中eslint没有生效,我建立了一个issues在跟踪这个问题。

2-15 更新 eslint其实是没问题的,只是需要自己去配置具体的规则

比如这样:

{
  "extends": "eslint-config-umi",
  "rules": {
    "semi": ["error", "never"]
  }
}

dva

今天尝试在umi中使用dva,通过官方的demo发现在umi中使用dva有两种方式,
区别在于是否使用umi-plugin-dva插件。

不使用插件

待补充

使用umi-plugin-dva插件

首先要安装这个插件

yarn add umi-plugin-dva

然后在.umirc.js中注册插件

export default {
  plugins: [
    'umi-plugin-dva'
  ]
}

然后重启项目

当前1.0.0-rc.15中还需要重启,以后可能会修复这个问题

现在umi会自动加载项目下models文件夹里的文件
现在在你需要使用数据的页面通过connect去取出数据就可以使用了

关于redux使用过程中的所思所想

写这篇blog的原因在于我今天早上在看一篇文章的时候,忽然想通了一个很久前别人问我的关于redux的问题,想一想,觉得还是记录下来,然后顺便再捋一捋redux相关的内容

为什么要写那么多不同的reducers,而不是写一个,想存什么就传什么

我现在的答案是:为了增加改变数据状态的成本
抽空来完善这个问题

webpack前端代码优化之旅

起因

最近接手了一个前端项目,由于之前前端开发人员比较多加上没有人很好的来约束管理,到我手上的时候已经变的比较恐怖,这里的恐怖主要指代码臃肿和体积庞大,随便改点东西,热加载都需要8秒左右的时间,在此基础上改需求已经异常难受,优化代码变的刻不容缓。

任务

简单列一下优化任务清单:

  1. 梳理第三方组件
  2. 使用DllPlugin优化开发环境
  3. 使用CommonsChunkPlugin优化生产环境

步骤 1

要完成这一步,我们要先分析一下当前代码的第三方组件使用情况,这里我推荐使用webpack-bundle-analyzer

yarn add webpack-bundle-analyzer

***.prod.js中添加

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
//...
plugins: [
  new BundleAnalyzerPlugin(),
]

然后运行编译命令,编译结束后本地会启一个服务并在浏览器中弹出一个页面,页面中就是当前编译后代码的组件使用情况,从中找出没用用且很大的组件,然后从代码中移除或注解

很多人在写代码的时候不会注意,就是只要你import的组件,不管是否使用,都会打包进去,切记开启no-unused-vars规则

这是个体力活儿,慢慢处理吧
当我完成这这一步的时候,我的项目已经从7mb的容量缩小到了3mb

步骤 2

我们代码已经比最开始清爽了很多,但我发现现在在开发的时候热加载还是4到5秒左右,还是不能忍受,所以我们现在要开始优化开发体验

webpack的组件dllplugin可以让你的热加载只编译业务部分,从而来大大提升热加载速度,这里我推荐使用autodll-webpack-plugin

yarn add autodll-webpack-plugin

然后在你的***.dev.js配置文件中加上

const AutoDllPlugin = require('autodll-webpack-plugin'); // dll
//...
plugins: [
  new AutoDllPlugin({
      inject: true, // will inject the DLL bundles to index.html
      filename: '[name].[hash].js',
      path: 'static/js',
      entry: {
        vendor: [
          'react',
          'react-dom',
          // 这里放步骤1中分析出来的比较大,但又必须使用的组件库
        ]
      }
    }),
]

完成这一步后这个项目的热加载速度已经降低到了3s以内,已经可以接受了

我的电脑年级比较大了,新电脑应该能到2s以内

步骤 3

我们来进行最后一步,优化此项目的线上表现
这里其实有几种思路,比如按需加载,但考虑到一些原因,这次的优化暂时不上按需,只是提取一下公共文件
这里我们要用到CommonsChunkPlugin
***.prodj.js

//...
plugins: [
  new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: module => {
        return module.resource && /node_modules/.test(module.resource)
      }
    }),
]

这里的意思是把node_modules下的所有包都提取到公共文件中
现在的webpack已经没有"boilerplatemanifest 代码可能在每次编译时都会变化"的问题,所以不用单独提取

总结

通过这3步,我在很短的时间内解决了当下这个项目的几个痛点,但优化的路还很长,而且优化永远是补救措施,更关键的还是从源头解决问题,比如整体团队的能力提升,整体代码质量的把控,都是需要很多精力去搞的事情,让我们一起加油吧

参考

DllPlugin
CommonsChunkPlugin
autodll-webpack-plugin
https://www.erichain.me/2017/07/11/2017-07-11-speeding-up-webpack-with-dllplugin/
creeperyang/blog#37

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.