webpack 从入门到放弃

问题: 1. 全局变量泛滥,2. 命名冲突, 3. 依赖关系管理,先去加载 a ,在去加载b, 否则就会报错;


二,模块化的初级阶段:立即执行函数
  1. var moduleA = function(){
  2. var a, b;
  3. return {
  4. message: function(c){
  5. alert(a+b+c)
  6. }
  7. }
  8. }()
  9. (function(window){
  10. // do something
  11. window.jQuery = window.$ = jQuery;
  12. })(window)

优点:模块内可以定义一些私有变量,缺点:仍然会污染全局变量,window.jquery ,没有解决模块依赖;


现代模块时代:
1. commonjs   , node 提出,同步不太适合浏览器,
  1.   var math = require('math');
  2. math.add(2, 3);
在服务器端,文件都是在硬盘中,而在浏览器中,文件需要网络穿过来,如果一个模块没传过来,整个应用都要停在那里等,浏览器假死;
2. requireJSAMD) , SeaJS ( CMD ),  
  1. require(['math'], function(math){
  2. math.add(2,3)
  3. })
异步,传入回调函数作为参数,等加载完成后执行;
3. ES6 Module, 目前比较流行;
  1. import math from 'math';
  2. math.add(2, 3);

模块化的目的:高内聚,低耦合;


前端的模块加载:

前端模块要在 浏览器中运行,必经的过程就是从服务器到浏览器的传输;两个极端方式:1. 每一个模块都发起一个请求; 2. 所有模块打包成一个,只请求一次;
显然,都不好;按需加载是比较合适的;

前端的模块不仅仅有js,还有css,less, sass,图片,他们都是模块,都可以用require的方式加载;
  1. require('./style.css');
  2. require('./style.less');
  3. require('./style.jade');
  4. require('./image.png');
webpack 本身只能处理js ,如果想处理其他类型的文件,就需要用到 loader 进行转换;loader 本身是一个函数,接受源文件作为参数,返回转换后的结果;
loader的特点:
  1. 可以链式调用,我处理完了交给你接着处理,但是最后一个loader必须返回javascript 
  2. loader 可以同步或者异步执行
  3. loader 可以运行在 nodejs中,所以可能做任何事情
  4. loader 通过参数来传递配置
  5. 插件让loader 有更多的特性

  1. var webpack = require('webpack');
  2. module.exports = {
  3. entry: './entry.js',
  4. output: {
  5. path: __dirname,
  6. filename: 'bundle.js'
  7. },
  8. module:{
  9. loaders: [
  10. {test: /.css$/, loader: 'style-loader!css-loader'}
  11. ]
  12. }
  13. }

添加插件,可以让loader 更加强大。插件有内置的,也有第三方的;
  1. var webpack = require('webpack');
  2. module.exports = {
  3. entry: './entry.js',
  4. output: {
  5. filename: 'bundle.js'
  6. },
  7. module: {
  8. loaders: [
  9. { test:/.css$/, loader: 'style-loader!css-loader'}
  10. ]
  11. },
  12. plugin: [
  13. new webpack.BannerPlugin('dujuncheng created')
  14. ]
  15. }
 

1. 安装

/ dudu01  执行 npm init ,
  1. npm init
会把该文件夹变成一个项目,会自动生成一个package.json 配置文件;
  1. cnpm install webpack --save
为了把webpack 添加到项目依赖里面;
package.json 文件里面会多了一个字段:
  1. "dependencies": {
  2. "webpack": "^2.5.1"
  3. }

2. webpack 会自动将文件进行打包

安装好了以后,我们新建两个文件:index.html, entry.js
  1. // index.html
  2. <div id='app'></div>
  3. <script src = 'bundle.js'>
  4. //entry.js
  5. document.getElementById('app').textContent = 'hello'
然后我们在控制台输入:
  1. webpack entry.js bundle.js

3. webpack 会自动分析 依赖,

webpack 会自动分析 entry.js里面依赖了哪些文件,会自动一起打包到bundle.js 里面;
我们新建一个bundle.js 文件,里面写的是:
  1. module.exports = 'dujuncheng'
在entry.js 里面引入:
  1. var name = require('./name');
  2. document.getElementById('app').textContent='hello'+name
通过
  1. webpack entry.js bundle.js
再次打包,我们就可以把entry.js依赖的name.js 一起打包进入bundle.js

4. loader 

webpack 本身只能处理js ,如果想处理其他类型的文件,就需要用到 loader 进行转换;loader 本身是一个函数,接受源文件作为参数,返回转换后的结果;
如果我们想使用一个loader ,那么我们必须要手动安装;
  1. cnpm install css-loader style-loader --save
在package.json里面就会多了loader:
  1. "dependencies": {
  2. "css-loader": "^0.28.1",
  3. "style-loader": "^0.17.0",
  4. "webpack": "^2.5.1"
  5. }
我们新建webpack.config.js, 里面的内容是:
  1. module.exports = {
  2. entry: './entry.js',
  3. output: {
  4. path: __dirname,
  5. filename: 'bundle.js'
  6. },
  7. module: {
  8. loaders:[
  9. { test:/.css$/, loader: 'style-loader!css-loader' }
  10. ]
  11. }
  12. }
多了一个module 对象,里面有一个数组 loaders, 数组的每一项都是对象,{test: /.css$/, loader: 'style-loader! css-loader'}
这就是告诉 webpack, 只要是css , 就需要用这两个loader 进行处理;

我们新建一个style.css,一会要把它打包进 bundle.js
  1. body {
  2. background-color: red
  3. }
  1. //entry.js
  2. require('./style.css');
  3. document.getElementById('app').textContent = 'dujuncheng' ;
我们把css  文件引入了js ,中间会自动用 css-loader , style-loader 进行处理;
  1. // 因为我们配置了webpack.config.js 配置文件,所以我们只要 webpack 就可以打包了
  2. webpack

5. source map

 在没有用sourcemap的时候,我们在开发人员工具那里,看到了有 index.html 和 bundle.js
bundle. js 不用我们关心,因为是打包后的,我们需要关心的是 source-map
  1. webpack --devtool source-map
 项目中会多了一个 bundle.js.map 的文件,我们的浏览器窗口下:
 source-map 方便了我们的调试,在name.js 文件里面,添加: debugger ,我们就可以在那个位置打一个断点;
 
如果我们不想在每一次的webpack 都带一个 devtool  我们可以在webpack.config.js 文件里面进行修改:
  1. module.exports = {
  2. entry: './entry.js',
  3. output: {
  4. path: __dirname,
  5. filename: 'bundle.js'
  6. },
  7. devtool: 'source-map',
  8. module: {
  9. loaders: [
  10. {
  11. test: /.css$/,
  12. loader: 'style-loader!css-loader'
  13. }
  14. ]
  15. }
  16. }

webpack 和 babel  进行配合
  1. cnpm install babel-loader babel-core babel-preset-es2015 --save-dev

code splitting
两个极端的的情况,我们把所有的文件都打包到一个文件里面,或者我们的每个文件都要分别打包;这两个都不好;
怎么做?
1. 分离业务代码和第三方库  [ vender ]
2. 分离css 文件
3. 按需加载  [ import() ]

第三方库更新较慢,并且可以锁版本,利用浏览器的缓存来加载第三方的库;
按需加载,用户访问了某一个路由的时候,再去加载相应的组件;

首先,我们想可视化的看到,我们的文件中是哪些比较占体积:webpack-bundle-analyzer
  1. npm install --save-dev webpack-bundle-analyzer
  2. //webpack.config.js
  3. var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
  4. // ...
  5. plugins: [new BundleAnalyzerPlugin()]
  6. // ...
通过这个插件,我们就可以很直观的分析啦;

分离第三方的库:我们的思路是:把node_module 里面的用到的 js插件,都放到vender.js 里面 
用webpack 自带的 commonChunkPlugin:
  1. new webpack.optimize.CommonsChunkPlugin({
  2. name: 'vendor',
  3. minChunks: ({ resource }) => (
  4. resource && resource.indexOf('node_modules') >= 0 && resource.match(/.js$/))
  5. }),


按需加载
很简单,需要改两个地方:路由声明组件的那个地方,output的文件名;
1. 路由声明组件:
  1. // import test1 from '@/components/test1'
  2. // import test2 from '@/components/test2'
  3. // import test3 from '@/components/test3'
  4. const test1 = () => import(
  5. /* webpackChunkName: "Emoji" */
  6. '@/components/test1')
  7. const test2 = () => import(
  8. /* webpackChunkName: "Emoji" */
  9. '@/components/test2')
  10. const test3 = () => import(
  11. /* webpackChunkName: "Emoji" */
  12. '@/components/test3')
2. chunkFilename修改
  1. filename: '[name].js',
  2. chunkFilename: '[name].chunk.js',
如果你用了 Babel ,就需要装上这个插件:babel plugin syntax dynamic import 来解析 import() 语法。修改 .babelrc :
  1. {
  2. "plugins": ["syntax-dynamic-import"]
  3. }










原文地址:https://www.cnblogs.com/dujuncheng/p/9e179f79465726eead2f70b3860d8eab.html