微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

关于webpack代码拆分的解析

最近在学习VUE的时候接触到了webpack,今天就留个小笔记,介绍一下webpack代码拆分

如果利用 webpack 将项目中的所有代码打包在一起,很多时候是不适用的,因为代码中有些东西我们总是希望将其拆分出来。比如:

  1. 样式表,希望利用 link 标签引入
  2. 使用概率较低的模块,希望后期需要的时候异步加载
  3. 框架代码,希望能利用浏览器缓存下部分不易变动的代码

下面是我在阅读 webpack 的官方文档时候,记录的一些笔记,部分地方使用了自己的话来讲,力图让它显得更易懂。

按需加载拆分

webpack 可以帮助我们将代码分成不同的逻辑块,在需要的时候加载这些代码

使用 require.ensure() 来拆分代码

require.ensure() 是一种使用 Commonjs 的形式来异步加载模块的策略。在代码中通过 require.ensure([]) 引用模块,其使用方法如下:

代码如下:

一个参数指定依赖的模块,第二个参数是一个函数在这函数里面你可以使用 require 来加载其他的模块,webpack 会收集 ensure 中的依赖,将其打包在一个单独的文件中,在后续用到的时候使用 jsonp 异步地加载进去。

rush:js;"> require.ensure(['./a'],function(require){ let b = require('./b'); let a = require('./a'); console.log(a+b) });

以上代码,a 和 b 会被打包在一起,在代码中执行到这段代码的时候,会异步地去加载,加载完成后执行函数里面的逻辑。

rush:js;"> let a = require('./a'); require.ensure(['./a'],function(require){ let b = require('./b'); console.log(a+b) });

如果这样写,那么 a 不会和 b 打包在一起,因为 a 已经被打包在主代码中了。

rush:js;"> require.ensure(['./c'],function(require){ let a = require('./a'); console.log(a) });

require.ensure(['./c'],function(require){
let b = require('./b');
console.log(b)
});

以上代码中两个模块都依赖了 c 模块,这个时候会拆分出两个模块,其中都包含了 c 模块,因为在实际运用中,以上两个 require.ensure 的执行顺序不确定,执行与否也不确定,因此需要将 c 模块都打包进去。

require.ensure 还可以传入第三个参数,这个参数用来指定打包的包名,对于上面这种情况,c 模块被打包入了两个包中,如果事先明确这两个包都会被使用,那么不妨将这两个包合并为一个,这样就不会有 c 模块被打包两次的问题了,所以可以将 chunkName 指定为同一个名字。

rush:js;"> require.ensure(['./c'],function(require){ let a = require('./a'); console.log(a) },'d');

require.ensure(['./c'],function(require){
let b = require('./b');
console.log(b)
},'d');

ok,这样以上两个 require.ensure 拆出来的包就合并为同一个了。

CSS 拆分

开发者,可能希望能将工程中的所有引入的 CSS 拆分为单个文件,这样可以利用缓存,且利用 CSS 和 JavaScript 并行加载,来加速 web 应用。

使用 css-loader

为了加载 css,这里需要用到 css-loader,配置方法如下:

rush:js;"> module: { loaders: [{ test: /\.css$/,exclude: /node_modules/,loader: 'css-loader' }] }

这样在代码中就可以写如下代码

rush:js;"> let css = require('./main.css'); console.log('' + css);

通过 require 一个 css 得到其内容,当然了这里 require('./main.css') 实际得到的是一个对象,需要调用其 toString 方法将其转换为字符串。在代码中引用一段 css,这常常不是我们想要的。为此可以使用 style-loader 在代码执行起来的时候,会将这些 css 插入到 style 标签中,只是这里 css 还是存在于 js 中的,是后来动态插入到页面中的:

rush:js;"> module: { loaders: [{ test: /\.css$/,loader: 'style-loader!css-loader' }] }

更多时候,是希望将 css 拆分为单个文件,然后使用 link 标签嵌入到 html 中,CSS 和 JavaScript 可以并行加载,css 还可以被缓存下来。

使用 extract-text-webpack-plugin 来拆分 css

为了使用这个插件首先需要通过 npm 来安装它:

rush:js;"> npm i --save-dev extract-text-webpack-plugin

然后在 webpack 的配置文件中使用该插件

rush:js;"> var ExtractTextPlugin = require('extract-text-webpack-plugin'); module.exports = function () { return { entry: './index.js',output: { path: './build',filename: 'bundle.js' },module: { loaders: [{ test: /\.css$/,// 在 loader 中使用该插件 loader: ExtractTextPlugin.extract('style-loader','css-loader') }] },plugins: [ // 将其添加插件中 new ExtractTextPlugin({ filename: 'bundle.css',disable: false,allChunks: true }) ] } }

需要注意的是,对于 webpack1 和 webpack2 这个插件的配置方法是不同的,差别比较细微,详情请看官方文档 extract text plugin for webpack 2

拆分业务代码与框架代码

通常一个 web 应用都会引用若干第三方库,这些第三方库通常比较稳定不会经常变动,但是如果将业务代码和框架代码打包在了一起,这样业务代码每次变动打包得到的结果都会变动,及时只改变了一个字符,浏览器也无法利用缓存,必须全部重新加载。因此,何不将第三方库单独打包在一起呢?

这里举个案例,一个 react 项目中使用了 react react-dom 这两个包,我希望将他们打包在一起,将业务代码打包在一起。

下面一步一步来:

1. 安装 react 和 react-dom:

rush:js;"> npm i react react-dom --save

2. 配置 entry,output 和 loader

先使用单入口,让代码工作起来。另外因为使用了 react 所以要使用 babel-loader 来加载 js

rush:js;"> // webpack.config.js

module.exports = {
entry: 'index.js',output: {
path: 'build/',filname: '[name]@[chunkhash].js'
},module:{
loaders:[{
test: /.js$/,loader: 'babel'
}]
}
}

3. 编写业务代码

index.js:

rush:js;"> import React from 'react'; import ReactDOM from 'react-dom';

var Hello = React.createClass({
render: function() {
return

Hello {this.props.name}
;
}
});

ReactDOM.render(<Hello name={'world'} />,document.getElementById('app'));

index.html:

rush:xhtml;">

原文地址:https://www.jb51.cc/js/37710.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐