Webpack 入门指迷

大概算是一份教程吧, 只不过效果肯定不如视频演示之类的好..
Webpack 最近在英文社区上经常看到, 留了心, 但进一步了解是通过下边的视频:
视频: How Instagram.com Works, Peter Hunt
Peter Hunt 也是 React 的传教士, 我由于对 React 的关注因此细看了视频
再后来是出现 React Hot Loader 这样的开发神器, 我认为 Webpack 应该很棒
http://gaearon.github.io/react-hot-loader/
为了解决简聊当中一些问题, 我消耗了很多时间了解 Webpack, 整理在这里

Webpack 是什么

https://github.com/webpack
Webpack 是德国开发者 Tobias Koppers 开发的模块加载器
Instagram 工程师认为这个方案很棒, 似乎还把作者招过去了
在 Webpack 当中, 所有的资源都被当作是模块, js, css, 图片等等..
因此, Webpack 当中 js 可以引用 css, css 中可以嵌入图片 dataUrl

对应各种不同文件类型的资源, Webpack 有对应的模块 loader
比如 CoffeeScript 用的是 coffee-loader, 其他还有很多:
http://webpack.github.io/docs/list-of-loaders.html
大致的写法也就这样子:

  module: {
    loaders: [
      { test: /\.coffee$/, loader: 'coffee-loader' },
      { test: /\.js$/, loader: 'jsx-loader?harmony' } // loaders can take parameters as a querystring
    ]
  },

CommonJS 与 AMD 支持

Webpack 对 CommonJS 的 AMD 的语法做了兼容, 方便迁移代码
不过实际上, 引用模块的规则是依据 CommonJS 来的

jsrequire('lodash') // 从模块目录查找
require('./file') // 按相对路径查找

AMD 语法中, 也要注意, 是按 CommonJS 的方案查找的

coffeedefine (require, exports. module) ->
  require('lodash') # commonjs 当中这样是查找模块的
  require('./file')

特殊模块的 Shim

比如某个模块依赖 window.jQuery, 需要从 npm 模块中将 jquery 挂载到全局
Webpack 有不少的 Shim 的模块, 比如 expose-loader 用于解决这个问题
https://github.com/webpack/docs/wiki/shimming-modules
其他比如从模块中导出变量...具体说明有点晦涩..

手头的两个例子, 比如我们用到 Pen 这个模块,
这个模块对依赖一个 window.jQuery, 可我手头的 jQuery 是 CommonJS 语法的
Pen 对象又是生成好了绑在全局的, 可是我又需要通过 require('pen') 获取变量
最终的写法就是做 Shim 处理直接提供支持:

js{test: require.resolve('jquery'), loader: 'expose?jQuery'},
{test: require.resolve('pen'), loader: 'exports?window.Pen'},

基本的使用

安装 webpack 模块之后, 可是使用 webpack 这个命令行工具
可以使用参数, 也可以配置 webpack.config.js 文件直接运行 webpack 调用
建议按照 Peter Hunt 给的教程走一遍, 基本的功能都会用到了
https://github.com/petehunt/webpack-howto

简单的例子就是这样一个文件, 可以把 ./main.js 作为入口打包 bundle.js:

js// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'       
  }
};

查找依赖

Webpack 是类似 Browserify 那样在本地按目录对依赖进行查找的
可以构造一个例子, 用 --display-error-details 查看查找过程,
例子当中 resolve.extensions 用于指明程序自动补全识别哪些后缀,
注意一下, extensions 第一个是空字符串! 对应不需要后缀的情况.

js// webpack.config.js
module.exports = {
  entry: './a.js',
  output: {
    filename: 'b.js'
  },
  resolve: {
    extensions: ['', '.coffee', '.js']
  }
}
js// a.js
require('./c')
➤➤ webpack --display-error-details
Hash: e38f7089c39a1cf34032
Version: webpack 1.5.3
Time: 54ms
Asset  Size  Chunks             Chunk Names
 b.js  1646       0  [emitted]  main
   [0] ./a.js 15 {0} [built] [1 error]

ERROR in ./a.js
Module not found: Error: Cannot resolve 'file' or 'directory' ./c in /Users/chen/Drafts/webpack/details
resolve file
  /Users/chen/Drafts/webpack/details/c doesn't exist
  /Users/chen/Drafts/webpack/details/c.coffee doesn't exist
  /Users/chen/Drafts/webpack/details/c.js doesn't exist
resolve directory
  /Users/chen/Drafts/webpack/details/c doesn't exist (directory default file)
  /Users/chen/Drafts/webpack/details/c/package.json doesn't exist (directory description file)
[/Users/chen/Drafts/webpack/details/c]
[/Users/chen/Drafts/webpack/details/c.coffee]
[/Users/chen/Drafts/webpack/details/c.js]
 @ ./a.js 2:0-14

./c 是不存在, 从这个错误信息当中我们大致能了解 Webpack 是怎样查找的
大概就是会尝试各种文件名, 会尝试作为模块, 等等
一般模块就是查找 node_modules, 但这个也是能被配置的:
http://webpack.github.io/docs/configuration.html#resolve-modulesdirectories

CSS 及图片的引用

英文的教程上有明确的例子:
https://github.com/petehunt/webpack-howto#5-stylesheets-and-images

jsrequire('./bootstrap.css');
require('./myapp.less');

var img = document.createElement('img');
img.src = require('./glyph.png');

上边的是 JavaScript 代码, CSS 跟 LESS, 还有图片, 被直接引用了
实际上 CSS 被转化为 <style> 标签, 而图片可能被转化成 base64 格式的 dataUrl
但是要主要在 webpack.config.js 文件写好对应的 loader:

js// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    path: './build', // This is where images AND js will go
    publicPath: 'http://mycdn.com/', // This is used to generate URLs to e.g. images
    filename: 'bundle.js'
  },
  module: {
    loaders: [
      { test: /\.less$/, loader: 'style-loader!css-loader!less-loader' }, // use ! to chain loaders
      { test: /\.css$/, loader: 'style-loader!css-loader' },
      {test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'} // inline base64 URLs for <=8k images, direct URLs for the rest
    ]
  }
};

url-loader

稍微啰嗦一下这个 loader, 这个 loader 实际上是对 file-loader 的封装
https://github.com/webpack/url-loader
比如 CSS 文件当中有这样的引用:

css.demo {
  background-image: url('a.png');
}

那么对应这样的 loader 配置就能把 a.png 抓出来,
并且按照文件大小, 或者转化为 base64, 或者单独作为文件:

module: {
  loaders: [
    {test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'} // inline base64 URLs for <=8k images, direct URLs for the rest
  ]
}

上边 ? 后边的 query 有两种写法, 可以看下文档:
http://webpack.github.io/docs/using-loaders.html#query-parameters

  • file-loader

由于 url-loader 是对 file-loader 的一个封装, 以因此带有后者一些功能:
https://github.com/webpack/file-loader
比如说, file-loader 有不弱的定义文件名的功能

jsrequire("file?name=[path][name].[ext]?[hash]!./dir/file.png")

对应 url-loader 当中如果文件超出体积, 就给一个这样的文件名..

打成多个包

有时考虑类库代码的缓存, 我们会考虑打成多个包, 这样不难
比如下边的配置, 首先 entry 有多个属性, 对应多个 JavaScript 包,
然后 commonsPlugin 可以用于分析模块的共用代码, 单独打一个包出来:
https://github.com/petehunt/webpack-howto#8-optimizing-common-code
https://github.com/webpack/docs/wiki/optimization#multi-page-app

js// webpack.config.js
var webpack = require('webpack');
var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('common.js');

module.exports = {
  entry: {
    Profile: './profile.js',
    Feed: './feed.js'
  },
  output: {
    path: 'build',
    filename: '[name].js' // Template based on keys in entry above
  },
  plugins: [commonsPlugin]
};

对文件做 revision

这个在文档上做了说明, 可以自动生成 js 文件的 Hash:
http://webpack.github.io/docs/long-term-caching.html

jsoutput: { chunkFilename: "[chunkhash].bundle.js" }
jsplugins: [
  function() {
    this.plugin("done", function(stats) {
      require("fs").writeFileSync(
        path.join(__dirname, "...", "stats.json"),
        JSON.stringify(stats.toJson()));
    });
  }
]

同时, 可以注册事件, 拿到生成的带 Hash 的文件的一个表
但是拿到那个表之后, 就需要自己写代码进行替换了.. 这有点麻烦
官网的 Issue 里提到个办法是生成 HTML 时引用 stats.json 的数据,
我此前的方案是生成 HTML 之后再进行替换, 相对赖上生成时写入更好一些

上线

  • 另一份配置文件

webpack --config webpack.min.js 指定另一个名字的配置文件
这个文件当中可以写不一样配置, 专门用于代码上线时的操作

  • 压缩 JavaScript

因为代码都是 JavaScript, 所以压缩就很简单了, 加上一行 plugin 就好了
http://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin

jsplugins: [
   new webpack.optimize.MinChunkSizePlugin(minSize)
]
  • 压缩 React

React 官方提供的代码是已经合并的, 这个是 Webpack 不推荐的用法,
在合并话的代码上进行定制有点麻烦, Webpack 提供了设置环境变量来优化代码的方案:

jsnew webpack.DefinePlugin({
  "process.env": {
    NODE_ENV: JSON.stringify("production")
  }
})

https://github.com/webpack/webpack/issues/292#issuecomment-44804366

  • CDN

替换 CDN 这个工作, Webpack 也内置了, 设置 output.publicPath 即可
http://webpack.github.io/docs/configuration.html#output-publicpath

代码热替换

虽然文档上写得挺复杂的, 但如果只是简单的功能还是很容易的

  1. 第一步, 把 'webpack/hot/dev-server' 加入到打包的代码当中,
    这个是对应 node_modules/webpack/ 目录当中的文件的:
js  entry: {
    main: ['webpack/hot/dev-server', './main'],
    vendor: ['lodash', './styles']
  },
  1. 启动服务器, 比如我是这样子的
bashwebpack-dev-server --hot --quiet

正常可以看到提示说服务器已经起来了
http://localhost:8080/webpack-dev-server/
如果有 index.html 的话, 直接访问网址应该就能开始调试了

React Hot Replace

调试 React 的话, 有这样的工具简直是神器了, 甚至不用刷新页面!
http://gaearon.github.io/react-hot-loader/getstarted/

entry: [
  'webpack-dev-server/client?http://0.0.0.0:8080', // WebpackDevServer host and port
  'webpack/hot/only-dev-server',
  './scripts/index' // Your appʼs entry point
]

我特意问了下作者为什么上边配置看起来不一样..
https://github.com/gaearon/react-hot-loader/issues/73#issuecomment-73679446
回复大致说是为了避免自动的强制刷新他用了特别的写法..
关于这项功能具体如何实现, 我没有深入了解过...

hot replace 非静态的网页

上边 localhost:8080 的方案并不适合复杂的页面,
于是文档上给出了一套稍微复杂一些的方案, 用来配合其他的服务器调试
大致的思路是这样的:

  1. Webpack 打包生成的那些静态资源用服务器 A 进行 serve
    这里说的 A 就是上边说的这个:
webpack-dev-server --hot --quiet
  1. 我们的 HTML 由 B 渲染, B 会引用 A serve 的静态资源
    B 生成的页面当中加上类似这样的代码:
<script src="http://<A 的地址>/assets/bundle.js">

还可能要设置一下 output.publicPath, 把所有静态资源指向 A
3. 文件修改时, webpack-dev-server 通过 socket.io 通知客户端更新

这个步骤在文档上写得有点难懂, 大概要多尝试几次才行, 我也弄错很多次
http://webpack.github.io/docs/webpack-dev-server.html

单独打包 CSS

因为公司里有这个需要求, 强制把 CSS 从 js 文件当中独立出来.
官方文档是以插件的形式做的:
http://webpack.github.io/docs/stylesheets.html#separate-css-bundle
参考文档但是注意一下函数参数, 第一第二个参数是有区别的, 比如这样用:

jsExtractTextPlugin.extract('style-loader', 'css!less')

第一个参数是编译好以后的代码用的, 第二个参数是编译到源代码用的.. 有点难懂..

感想

Webpack 的报错挺不友好的, 最初的时候我看着模块找不到没法搞明白
这种时候把中间过程打印出来看是不错的选择:

webpack --display-error-details

另一个报错是没有对应 loader 的提示.. log 可能很长找不到重点
我建议是先自己去想想什么地方需要考虑 loader 吧... 可能就知道了
我还遇到就是源码里有使用 dataUrl 导致报错... 确实奇怪了

不说这些坑的话, Webpack 我认为是我目前接触到最好的前端开发方案
很多功能之前 FIS 文档上看到过, 但 FIS 相对重一些我始终没上手
而 Webpack 一上来就绕过了此前公司用 RequireJS 打包时遇到的各种问题

如果去扫 Webpack 的文档的话, 还有很多功能我完全没涉及到..
http://webpack.github.io/docs/

你可能感兴趣的文章

讨论区

+1

怎么在 webpack 中使用 uikit ?http://segmentfault.com/q/1010000002583716

王道中强流 · 2015年03月07日

+1

目前发现的一个潜在的问题:
引进css时,会为每一个不同的require生成一个style标签。即使在压缩模式下也是如此
而IE 6-9 有一个不太著名的bug:
http://blogs.msdn.com/b/ieinternals/archive/2011/05/14/10164546.aspx

即style与link[rel="stylesheet"]加起来的上限数量是31个,在此之后就不认了

当然这个bug也好解决,都打到同一个style标签里就行了,回头研究一下

kpaxqin · 2015年03月18日

+0
回复 kpaxqin

赞, 有靠谱的办法的话记得分享下

题叶 · 2015年03月18日

+0

最近还有个比较迷惑的问题,这东西怎么和单元测试框架配合?
现有单元测试框架针对amd模块都有解决方案,但使用webpack的时候更习惯直接写nodejs风格的代码,怎么让单元测试框架识别?当然可以做个wrapper的grunt任务,但总觉得应该有现成的解决方案

kpaxqin · 2015年03月20日

+0
回复 kpaxqin

Facebook 有个 Jest 是使用 CommonJS 风格的. 但是具体 AMD 怎么搭配还真不知道.

题叶 · 2015年03月20日

+2
回复 题叶

不光是代码风格的问题,基于webpack写的代码其依赖关系也是适应webpack解析规则的(甚至有在webpack中配置的alias),如何让测试框架正确识别被测试代码的依赖是首要问题
官网testing一章太简略了……
目前用webpack写了个比chat稍微复杂点的demo,感觉坑还是不少……

kpaxqin · 2015年03月22日

+0
回复 kpaxqin

有道理, 跟其他规范下的工具要配合不是短时间会成熟的.

题叶 · 2015年03月22日

+0

tes

kpaxqin · 2015年03月27日

+0
回复 题叶

单元测试的问题后来发现比较好解决,只是官方示例不太清楚要自己摸索下,我用的grunt-contrib-testem。把单元测试代码打成一个testBundle.js,在测试代码中通过

jsrequire("../../src/foo/bar.js")

引入被测试的模块

kpaxqin · 2015年03月27日

+0

请问下uglifyJs 是怎么和webpack集成到一起.?

BlakeJia · 2015年03月27日

+0
回复 BlakeJia

如果只是压缩代码的话, 官方给了一个插件写法 http://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin

题叶 · 2015年03月27日

+0

请问 webpack 可以实现条件加载吗,例如:
···
if(flag == 1){
require("a.js");
}else{
require("b.js");
}
···
要求客户端只会加载 a 或者 b 中的一份文件。

小魔女 · 2015年04月14日

+0
回复 小魔女

前端的异步加载文档有提到, 我没探索过..
http://dontkry.com/posts/code/single-page-modules-with-webpack.html

题叶 · 2015年04月14日

+0

webpack看了一段时间,还是没敢从requirejs转过来
1.现在网站是多页面的,可能有百来个entry point,是不是都得定义在配置文件里?
2.原先按照业务逻辑,使用了requirejs的 bundle 把相同业务逻辑的个entry point都合成一个文件了,用webpack是不是就不能这样做了?

Niphor · 2015年04月23日

+0
回复 Niphor

我没有实践过, 记得 Instagram 介绍的时候他们自家有 17 个页面, 正常.., 视频里边:
http://www.tudou.com/programs/view/6KB6lNbVzhs/
entry 是数组形式的, 就算上百也应该是能够用代码完成的.

第二个问题没看明白, 照说当成 Browserify 理解那样子...

题叶 · 2015年04月23日

+0
回复 题叶

第二个问题:
比如有 entry1.js、entry2.js、entry3.js,原本用requirejs,直接合并成entry.js了,然后配合requirejs的bundle,页面上直接调用 requirejs([entry1],callback),只会执行entry1里面的代码。
但是webpack 打包entry,如果几个合在一起,它们都会执行,然后将最后一个的返回值export出去。
entry1.js、entry2.js、entry3.js都执行了一次,这就很蛋疼了。

Niphor · 2015年04月23日

+0
回复 Niphor

_< 不会呃, 要不还是去问问大神吧.. https://gitter.im/webpack/webpack

题叶 · 2015年04月23日

+0

请教一下,html中加载两个JS文件,一个是module配置文件(id和url对应的形式),另一个是入口文件,入口文件中用了这种形式define(['moduleID'],function(module){}),现在用webpack打包,就加载不到moduleID,这种情况该怎么解决呢?

ludiusyan · 2015年05月05日

+0
回复 ludiusyan

Webpack 虽然宣称支持 AMD, 实际上模块引用的路径是按照 CommonJS 来的, 仅仅支持的写法. 建议用 webpack --display-error-details 查看下到底跟它期望的差多少?

题叶 · 2015年05月05日

+0
回复 题叶

这种方式查看过,加载方式相当于把moduleID当成相对路径了,找不到的情况下又会到全局的node_module下找。现在就是想找个解决方法,静态module还是按配置文件(requirejs.config)的写法,要求在入口文件中,不论使用define([moduleID],function(){}),require(moduleID),参数都是ID,而不是路径,不知道有没有什么好的建议?

ludiusyan · 2015年05月05日

+0
回复 ludiusyan

没有想到办法, 同时我对兼容 requirejs.config 不抱什么期望..

题叶 · 2015年05月05日

+0
回复 题叶

额,好吧,谢谢了

ludiusyan · 2015年05月05日

+0
回复 ludiusyan

实在有需要只能问下作者了... https://gitter.im/webpack/webpack

题叶 · 2015年05月05日

+0

chunkFilename 是什么,没看懂

sanae · 2015年05月06日

+0
回复 Niphor

我是在配置文件里面读取 需要添加为 entry point 的全部文件名,自动生成 entry point 的 list。这样就几乎一劳永逸了:)

798bin · 2015年05月14日

+0
回复 798bin

或者把entry point放一个目录里,以后直接扫目录文件生成也是极好的。

对于第二个问题,有什么高见没有?

Niphor · 2015年05月15日

+0

卤煮好,我用webpack打包css在IE8下无效,报Object doesn't support property or method 'bind'

小霸王 · 2015年05月25日

+0
回复 小霸王

不知道这个能帮上你吗, Webpack 本身对低版本支持很少提到, 好像是不怎么样, 但也可能是具体的 loader 写法问题.
https://github.com/webpack/webpack/issues/12
https://github.com/webpack/style-loader/issues/42

题叶 · 2015年05月25日

+0
回复 题叶

感谢卤煮答案

小霸王 · 2015年05月26日

+0

楼主,看完视频一直有一个疑问就是Instagram是如何确保异步加载过程中的css加载的,使得客户端能够呈现完美的效果的?

墨白 · 2015年07月10日

+0
回复 墨白

好问题... 视频没讲, 我们也遇到了, 当时用的办法是分离出一个 CSS 文件直接加载. 看 Instagram 的请求, 他们是加载的 JavaScript 的时候就阻塞页面的, 页面跟样式一起出来.

题叶 · 2015年07月10日

+0
回复 题叶

Pete不是说把css也打包,跟js一样采用异步加载吗?难道是先一步加载css包,再一步加载js包?

墨白 · 2015年07月10日

+0
回复 墨白

Instagram 的实现跟我们不一样啊, 看下 https://instagram.com/

题叶 · 2015年07月11日

+0

楼主,我想请教一下,现在我用npm无法下载webpack,据说是由于不支持了,那如果我想用webpack的话怎么办呢?

墨白 · 2015年07月17日

+0

一个自己写的plugin能区别 -p 和 -w 编译嘛,不想用两个配置文件。

不一 · 2015年07月17日

+0
回复 墨白

我还是能下载的, 不清楚你说的问题啊..

题叶 · 2015年07月17日

+0
回复 不一

不清楚, 其实我觉得两个配置文件还算清晰吧.. 或者用 Gulp 配置一下写在一个文件里? 也可以去他们的 Gitter 上问问

题叶 · 2015年07月17日

+0
回复 题叶

我使用webpack --display-error-details进行打印,发现路径的查找不是按照commonJS的规范来的,还是去寻找同级目录,我在C盘的Roming目录下有node-modules,没有从那边去找。还没发现原因

委员会主任 · 2015年08月05日

+0
回复 委员会主任

路径查找是基于 CommonJS 的, 可是好像不会去全局的 NODE_PATH 里搜索.

题叶 · 2015年08月06日

+0

想问一下如何讲bundle.js 生成为真实的js文件

海诺 · 2015年08月16日

+0

求推荐一些英文社区

QuoniamYIF · 2015年10月27日

+0
回复 QuoniamYIF

Webpack 的 Twitter, Gitter, GitHub Issue~

题叶 · 2015年10月27日

+0
回复 海诺

没看明白... bundle.js 就是真实的文件啊

题叶 · 2015年10月27日

+0

推荐加入472408579 webpack群

sundy · 2015年11月09日

+0

{test: require.resolve('jquery'), loader: 'expose?jQuery'}, 这个用法,没搞懂,求指教

沧浪的羽毛 · 2015年12月31日

+0
回复 沧浪的羽毛

test 用来判断资源的地址是否匹配, loader 控制使用哪个加载器, 其中 ?jQuery 是加载器的参数. expose-loader 是用来把模块的对象暴露到全局的.

题叶 · 2015年12月31日

+0
回复 题叶

谢谢,刚搞明白,这个是不是针对AMD或commonjs的模块用的,其他的没有什么用

沧浪的羽毛 · 2015年12月31日

+0
回复 题叶

{test: require.resolve('pen'), loader: 'exports?window.Pen'} 这个的意思是 pen这个模块是个全局的?然后其他地方需要用require来用么??没搞懂

沧浪的羽毛 · 2015年12月31日

+0
回复 沧浪的羽毛

我也觉得不好懂, 但是从结果上说, Pen 是一个没有模块化的类库, 直接绑定在 window 对象上, 而加载器的作用是在调用 require('pen') 的时候能正确拿到 window.Pen 的数据. 具体要看 loader 的 README, 麻烦的时候还要自己尝试一下效果.

题叶 · 2015年12月31日

+0
回复 题叶

试了一下,根据生成的结果看,就是把一个模块内的变量返回到全局的WINDOWS上

沧浪的羽毛 · 1月4日

+0
回复 题叶

另外,顺便问一下,webpack跟requirejs的打包,比起来有哪些好久?

沧浪的羽毛 · 1月4日

+0
回复 沧浪的羽毛

好处是吗? Webpack 考虑问题非常全面, 多种加载方案语法, 非 js 的静态资源, 异步加载, 分包, 热替换, 多种情况都考虑到了, requirejs 是早期的方案的所以很多情况都没纳入考虑.

题叶 · 1月4日

+0

React Hot Replace怎么处理多个entry入口文件啊?

tg · 1月28日

+0
回复 tg

我现在是每个冒泡的位置都处理一下的.

题叶 · 1月28日

+0
回复 题叶

能不能给点代码参考下?

tg · 1月28日

+0
回复 kpaxqin

这文档里只是说不能@import超过31个

龙腾道 · 3月7日

+0

请问一下,在 webpack 里,我使用了一个 bootstrap-dialog.js 的bootstrap.js 的插件,由于 bootstrap 不支持 AMD且需要 jQuery,所以我先将 jQuery 配置为全局的;bootstrap-dialog.js 需要 bootstrap的 modal 功能,因此在打包构建后报“Cannot read property 'modal' of undefined”错误,请问在 webpack 里如何配置能解决这个问题,谢谢。

BeefScript · 4月7日

+0
回复 BeefScript

按照我用AMD的经验来推测,应该是要把bootstrap也配置为全局的

array_huang · 4月15日

+0

new webpack.DefinePlugin({
"process.env": {

NODE_ENV: JSON.stringify("production")

}
})
这里为何要用JSON.stringify再包一层?

灯卧佛 · 7月12日

+0

FIS,我觉得比webpack好上手

superlbr · 8月6日

+0
回复 小魔女

if(flag == 1) {

require.ensure(["module1"], function(require) {
    require("module1");
}

} else ...

浩哥_ · 8月17日

展开评论

本文隶属于专栏

题叶, JiyinYiyong

FP, GUI & Writing, http://tiye.me

题叶 题叶

作者

SegmentFault

一起探索更多未知

下载 App