• 主页
  • github
  • 简历

Tagged: javascript

升级到webpack4不完全指南

webpack在2018年2月25号发布最新的4.0版本, 更新了以下内容:

  • 性能大幅提升(没感觉..)
  • 新增mode配置, 可选择设置为development和production, 实现零配置启动(意义不大…)
  • 废弃CommonsChunkPlugin, 使用optimize.splitChunks和optimization.runtimeChunk替代
  • 支持WebAssembly
  • 支持CommonJS, AMD, ESM等模块系统, 可以直接导入.mjs扩展名的模块文件, 对wasm模块也有实验性的支持

今天我将自己维护的React脚手架从webpack2升级到了4, 记录一下需要改动的地方. 本篇是”不完全指南”, 欢迎补充更多内容

升级依赖版本

  • webpack: 2.2.1 -> 4.1.1
  • webpack-dev-middleware: 1.10.0 -> 3.0.1
  • html-webpack-plugin: 2.28.0 -> 3.0.6
  • extract-text-webpack-plugin: 2.0.0 -> 4.0.0-beta.0
  • copy-webpack-plugin: 4.0.1 -> 4.5.1
  • react-hot-loader: 3.0.0-beta.7 -> 4.0.0

webpack config添加mode字段

1
2
3
4
// webpack.config.js
module.exports = {
mode: 'development' // 或者 production
}

删除UglifyJsPlugin插件

在mode: production下, 会自动进行代码压缩. 可以修改配置项 optimization.minimize: 'on'/'off' 控制是否启用, 修改配置项 optimization.minimizer: {} 调整默认行为

删除CommonsChunkPlugin插件

替代为配置项 optimization.splitChunks, 可配置内容如下:

最简单的配置

1
2
3
4
5
optimization: {
splitChunks: {
chunks: 'all',
},
}

手动定制vendor内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module.exports = {
entry: {
vendor: ['react', 'react-dom', 'redux']
},
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
chunks: 'initial',
name: 'vendor',
test: 'vendor',
enforce: true,
},
},
},
},
}

字符串或者正则匹配控制vendor内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module.exports = {
entry: {
vendor: ['react', 'react-dom', 'redux']
},
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
chunks: 'initial',
name: 'vendor',
test: path.resolve(__dirname, '../node_modules'), // 或者 test: /node_modules/
enforce: true,
},
},
},
},
}

函数控制vendor内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module.exports = {
entry: {
vendor: ['react', 'react-dom', 'redux']
},
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
chunks: 'initial',
name: 'vendor',
test: module => /node_modules/.test(module.context),
enforce: true,
},
},
},
},
}

react-hot-loader

原来的写法是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// index.js
import React from 'react';
import ReactDom from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import App from './App';
const render = (Component) => {
ReactDom.render(
<AppContainer>
<Component />
</AppContainer>,
document.getElementById('app'),
);
};
render(App);
if (module.hot) {
module.hot.accept('./App', () => { render(App); });
}
// App.jsx
import React, { Component } from 'react';
export default class App extends Component {
render() {
return <div>App</div>
}
}

现在改为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// index.js
import React from 'react';
import ReactDom from 'react-dom';
import App from './App';
ReactDom.render(
<App />,
document.getElementById('app'),
);
// App.jsx
import React, { Component } from 'react';
import { hot } from 'react-hot-loader';
import Hello from './components/Hello';
class App extends Component {
render() {
return <div>App</div>
}
}
export default hot(module)(App);

还有, 在webpack html-webpack-plugin-after-emit事件回调中, 删除 hotMiddleware.publish({ action: 'reload' }); 语句

引用内容

webpack@4.0.0 release log
webpack 4.0.0-alpha.5 feedback #6357



查看更多

SVG图片动态修改颜色, 并渲染

动态生成svg字符串, 并将其转为Image对象


查看更多

兼容不支持HTML5 Blob的浏览器

部分浏览器(webview)不支持HTML5新增的Blob, 会抛出异常TypeError Illegal Constructor, 这种情况可以使用BlobBuilder做兼容处理


查看更多

Javascript函数安全调用小技巧

最近遇到了一个问题, 场景如下. 有一部分功能需要依赖第三方js文件, 由于业务代码是离线化的而第三方js文件却是从网络获取, 其加载时间必定晚于业务代码执行时间


查看更多

使用rollup.js编译JavaScript代码

rollup 是一款小巧的 JavaScript 打包工具, 它更适合用作库应用的构建工具


查看更多

react-redux 原理分析

探究 react-redux 源码, 解密 Provide 和 connect 到底做了什么


查看更多

JS模块规范区别(CommonJS,AMD,CMD,UMD,ES6)

JS模块规范区别(CommonJS, AMD, CMD, UMD, ES6)


查看更多

关于setTimeout / setImmediate / process.nextTick的区别

常见面试题, setTimeout / setImmediate / process.nextTick的区别, 并说出代码执行顺序


查看更多

在web中唤起APP并检查是否成功

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// 检查app是否打开
function checkOpen(cb) {
const clickTime = +(new Date());
function check(elsTime) {
if (elsTime > 3000 || document.hidden || document.webkitHidden) {
cb(true);
} else {
cb(false);
}
}
// 启动间隔20ms运行的定时器,并检测累计消耗时间是否超过3000ms,超过则结束
let count = 0;
let intHandle = null;
intHandle = setInterval(() => {
count++;
const elsTime = +(new Date()) - clickTime;
if (count >= 100 || elsTime > 3000) {
clearInterval(intHandle);
check(elsTime);
}
}, 20);
}
/**
* 唤起app
* @param {any} uri app schema
* @param {any} fallback 唤起失败回调
*/
function openApp(uri, fallback) {
const ifr = document.createElement('iframe');
ifr.src = uri;
ifr.style.display = 'none';
if (fallback) {
checkOpen((opened) => {
if (!opened) {
fallback();
}
});
}
document.body.appendChild(ifr);
setTimeout(() => {
document.body.removeChild(ifr);
}, 2000);
}

参考

http://www.cnblogs.com/lyre/p/6169028.html
http://blog.html5funny.com/2015/06/19/open-app-from-mobile-web-browser-or-webview/



查看更多

2017百度前端学院热身题非"主流"答案

今天注意到17年百度前端学院活动开放注册了, 作为一只入行一年的小前端, 希望能参与这次活动锻炼一下自己. 按照要求报名后回到首页, 看到有热身任务, 于是点开来玩玩.


查看更多