Webpack代码拆分

时间:2017-04-02 14:54:30

标签: javascript webpack

我试图用webpack设置我的项目,我已经读过有关代码分裂的内容,我正在尝试创建两个独立的bundle,一个用于实际的应用程序代码,另一个用于库和框架。所以我的webpack配置看起来像这样:

entry: {
    app: './app/index.js',
    vendor: './app/vendor.js'
},
output: {
    filename: '[name].[chunkhash].js',
    path: path.resolve(__dirname, 'public/js')
},

watch: true,

module: {
    rules: [{
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
            use: 'css-loader'
        })
    }]
},

plugins: [
    new ExtractTextPlugin('styles.css'),
    new webpack.optimize.CommonsChunkPlugin({
        name: 'vendor'
    })
]

在我的vendor.js包中我只有一行:

 import moment from 'moment';

当我尝试在我的app.js文件中使用它时,它告诉我,那个时刻没有定义。那么,我不能得到的东西,捆绑是否有共同的范围?如果没有,那么我如何访问我已经在另一个捆绑中导出的变量,如果我不能,那么即使是像这里描述的那样拥有供应商捆绑包的重点https://webpack.js.org/guides/code-splitting-libraries/

3 个答案:

答案 0 :(得分:6)

捆绑包不共享范围。实际上webpack尊重每个模块的范围,就像Node.js一样,所以你不能使用其他模块中的任何东西,除非你导入它,即使它在同一个包中。

您需要在每个使用它的模块中导入Public class Tab2Vid extand Fragment implement View.OnClickListener { Public View onCreateView(LayoutInflater inflater, ViewGroup container ,Bundle savedlnstanceState) { View rootView = inflater.inflate(R.layout.tab2video, container, false); Button play = (Button)rootView.findViewById(R.id.btnplay); return rootView; } Public void onClick(View view)( switch (view.getId()) { case R.id.btnplay: Toast.makeText(getActivity(),"Btn Play clicked", Toast.LENGTH_SHORT).show(); break; default: return; } } } 。这并不意味着您多次包含其源代码。 Webpack包含一次源代码,每次导入都会引用它。

代码拆分,在这种情况下为moment,只是将源放入供应商捆绑包中,并且捆绑包中的每个导入都将引用供应商捆绑包。这意味着您不会将供应商依赖项与您的应用程序包一起发布,因此浏览器可以缓存供应商捆绑包。当您在不更改供应商捆绑包的情况下发布应用程序的新版本时,浏览器只需要下载应用程序包,因为它已经拥有正确的供应商捆绑包。

让我们考虑一下这个非常简短的示例应用程序:

CommonsChunkPlugin

如果没有import moment from 'moment'; console.log(moment().format()); 生成的包(不是uglified),则为:

CommonsChunkPlugin

那是470 KB,因为它包含了捆绑包中的整个vendor.js 470 kB 0 [emitted] [big] vendor app.js 470 kB 1 [emitted] [big] app 来源,更糟糕的是,另一个也使用moment的捆绑包也包含整个源代码。供应商不应该在这里使用它,但想到另一个需要使用它的捆绑包。当您在应用程序中更改某些内容时,用户必须再次下载整个470 KB。

使用moment

CommonsChunkPlugin

现在应用程序下降到504字节。当您更改应用程序时,用户只需下载此小包(假设 app.js 504 bytes 0 [emitted] app vendor.js 473 kB 1 [emitted] [big] vendor 已被缓存)。这也意味着使用vendor.js的任何其他捆绑包也会引用moment,而不是在捆绑包中包含源。

vendor.js的大小略有增加,因为webpack需要一些额外的代码来处理来自另一个bundle的导入。这还需要在vendor.js之前加载vendor.js

为了简洁起见,我省略了文件名中的哈希值,但是它们是缓存清除所必需的。有关详细信息,请参阅Caching

答案 1 :(得分:3)

我看到了问题,但它与代码拆分无关。根据具体情况,有不同的方法可以实现这一目标:

vendor.js中需要index.js

vendor.js

export default moment from 'moment';

index.js

var moment = require('vendor.js');
console.log(moment());

使用导入加载器:

导入加载器允许您使用依赖于特定全局变量的模块。这对于依赖全局变量(如$或这是窗口对象)的第三方模块非常有用。导入加载程序可以添加必要的需求('无论什么')调用,因此这些模块可以与webpack一起使用。

require("imports-loader?$=moment,angular!./index.js");

通过插件:

您可以通过插件将momentJS暴露给windows对象,因此您可以从index.js访问window.moment

new webpack.ProvidePlugin({
    "window.moment": "moment"
}),

答案 2 :(得分:0)

所以我一直在努力将一个对象及其所有方法从一个单独的.js文件导入到app.js,同时使用webpack。事实证明,你所要做的就是....

假设您在var xys{};

中定义了此ourjsfile.js个对象

你已经定义了各种方法,比如..

xyz.add = function(){ ... };

在文件的末尾,您只需添加..

module.exports = xyz;

多数民众赞成!现在,为了在app.js中使用此对象(变量),您必须按以下要求...

var xyz = require('./ourjsfile');

瞧瞧!!!该对象已导入。对于这样一个简单的解决方案,这件事让我的头发拉得太久了。