WebPack:更优秀的模块依赖管理工具,及require.js的缺陷
jopen
10年前
注* 之前的这篇文章: JavaScript代码组织结构良好的5个特点,作者以reuqire.js为举例,提出应该使用模块化的代码组织方式去管理你的JavaScript代码,并提出了一些注意事项,在此文的评论中有人指出WebPack是比require.js更为优秀的代码组织管理工具,并列举了require.js的一些缺陷。
WebPack 是一个模块打包工具,你可以使用WebPack管理你的模块依赖,并编绎输出模块们所需的静态文件。
它有两种模块加载模式
同步加载模式: CommonJS (Node.JS)的模式
var commonjs = require("./commonjs");
异步加载模式:即 AMD 模式,与require.js相同
define(["amd-module", "../file"], function(amdModule, file) { require(["big-module/big/file"], function(big) { var stuff = require("../my/stuff"); }); });
注* 与异步加载相比(AMD),同步加载的写法要简单得多,不必处理诸多回调。但在前端采用此方案的性能会非常非常差,无法投入生产环境,所以各种模块加载工具都会自带一些build工具,按照代码内定义的模块依赖关系,将所需模块按依赖次序压缩合并,打包成一两个静态文件,以下来自该评论:
如果你用过webpack,你就不会用require.js去组织你的代码。
webpack的优势:
- require.js的所有功能它都有
- 编绎过程更快,因为require.js会去处理不需要的文件
还有一个额外的好处就是你不需要再做一个封装的函数,require.js中你得这样:
define(['jquery'], function(jquery){})
然后你就会发现你有十级深度的依赖,这太扯了,你不得不使用下面的结构。
define(function(require, exports, module){ var _ = require('underscore'); var helpers = require('./helpers'); var constants = require('../constants'); var utils = require('../utils');
现在你需要一个很大的封装去定义每个模块,然后你需要在在require.js的配制文件中将每个模块的路径都配出来(下面是我以前用的一个配制):
require.config({ baseUrl: '/scripts', paths: { '非死book' : '//connect.非死book.net/en_US/all', // '非死book' : '//connect.非死book.net/en_US/sdk/debug' 'requirejs' : '../bower_components/requirejs/require', 'react' : '../bower_components/react/react-with-addons', 'underscore' : '../bower_components/lodash/dist/lodash', 'futures-requirejs' : '../bower_components/futures-requirejs/future', 'jquery' : '../bower_components/jquery/jquery', // 'phaser' : '../bower_components/phaser/build/phaser', 'phaser.filters' : '../bower_components/phaser/filters/', 'phaser' : '../thirdParty/phaser/Phaser', 'snap' : '../bower_components/Snap.svg/dist/snap.svg', 'proton' : '../thirdParty/Proton', 'copyProperties' : '../thirdParty/copyProperties', 'flux' : '../bower_components/flux/dist/Flux', 'eventEmitter' : '../bower_components/eventEmitter/EventEmitter', 'pixi' : '../bower_components/pixi/bin/pixi', 'crossroads' : '../bower_components/crossroads/dist/crossroads', 'signals' : '../bower_components/js-signals/dist/signals', 'hasher' : '../bower_components/hasher/dist/js/hasher', 'async' : '../bower_components/async/lib/async', 'socket.io-client' : '../bower_components/socket.io-client/dist/socket.io', 'html2canvas' : '../bower_components/html2canvas/build/html2canvas.min', 'hammer' : '../bower_components/hammerjs/hammer', 'touch-emulator' : '../bower_components/hammer-touchemulator/touch-emulator', 'moment' : '../bower_components/moment/moment', // 'famous' : '../bower_components/famous', 'tinygradient' : '../bower_components/tinygradient/tinygradient', 'page' : '../bower_components/page/index', // 'faker' : '../bower_components/faker/dist/faker', 'faker' : '../thirdParty/Faker', 'perlin' : '../thirdParty/Perlin', 'tinycolor' : '../vendors/tinycolor', // 'flux' : '../../node_modules/flux/index', 'client' : './', 'errors' : './errors', 'server' : '../../server', }, packages: [{ name : 'API2', location : '../bower_components/api2/src/', main : 'API' }], shim: { 'phaser.filters/Fire': { deps: ['phaser'], }, 'page': { exports: 'page' }, 'snap' : { exports: 'Snap' }, 'html2canvas' : { exports: 'html2canvas' }, '非死book' : { exports: 'FB' }, // 'underscore': { // deps: [], // exports: '_' // }, 'phaser': { exports: 'Phaser' }, 'pixi': { exports: 'PIXI' }, 'hammer': { exports: 'Hammer' }, 'touch-emulator': { exports: 'TouchEmulator' }, 'proton': { exports: 'Proton' }, 'moment': { exports: 'moment' } } });
但是你用webpack你不需要做上面这些东西,你只需要:
var react = require('react');
真的,不需要任何模块的定义。
当然,如果你需要一些特别的别名,你需要写多一点,这是一个webpack.config的例子:
alias: { // Build // - Webpack config; webpackConfig : absPath('webpack.config.js'), // Structure // - Aliases to the big building blocks of the app; server : absPath('/src/server/'), assets : absPath('/src/assets/'), app : absPath('/src/app/'), client : absPath('/src/client/'), // Components // - Aliases to npm, bower and other modules; bowerComponents : absPath('bower_components'), otherModules : absPath('other_modules'), nodeModules : absPath('node_modules'), // Application // - Aliases for the most used files in the app; errors : 'client/errors', constants : 'client/constants', utils : 'client/utils', RCSSW : 'client/utils/RCSSW', 'react-tooltip' : 'otherModules/react-tooltip/src/index.js', // Custom libs // - Rename some libs; // - Non npm libs; API2 : 'bowerComponents/api2/src/API', copyProperties : 'otherModules/copyProperties', eventEmitter : 'wolfy87-eventemitter', hammer : 'hammerjs', underscore : 'lodash', // We use the exact same PIXI that Phaser uses. PIXI : "otherModules/phaser/PIXIWrapper.js", pixi : "otherModules/phaser/PIXIWrapper.js", // phaser : "nodeModules/phaser/dist/phaser-arcade-physics.js", phaserUnFixed : "nodeModules/phaser/build/custom/phaser-no-physics.js", phaser : "otherModules/phaser/phaser-wrapper.js", tinycolor : 'tinycolor2', // Yes, is 2, is right! // As said here http://非死book.github.io/react/docs/addons.html react : 'react/addons', }
注意到区别了吗?非常明显。
你在浏览器定义的层次需要在package.json文件中配置。
来自:http://ourjs.com/detail/54963e2a8a34fa3204000013
来自:http://ourjs.com/detail/54963e2a8a34fa3204000013