一步一步学WebPack 2

一步一步学WebPack2

最近将webpack的使用总结一下,便于下一步的使用。本文通过若干的demo,让你一步一步学会使用webpack。webpack中一切都是模块,所有的一切(JS,CSS,图片,HTML)都可以被视作模块,通过require加载。模块加载器会把所有的模块最终打包生成一个巨大的“bundle.js”文件,并且会一直不停进行加载!所以Webpack通过大量的特性去分割你的代码,生成多个“bundle”片段,并且异步地加载项目的不同部分。

npm install http-server -g

Demo1 - Start

  • 建立node项目:npm init ,名字为demo1,得到package.json文件
{
  "name": "demo1",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/fujusong/webpack-starter.git"
  },
  "keywords": [
    "webpack",
    "starter"
  ],
  "author": "sofu",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/fujusong/webpack-starter/issues"
  },
  "homepage": "https://github.com/fujusong/webpack-starter#readme",
  "devDependencies": {
    "webpack": "^2.6.1"
  }
}
  • 创建index.html ,并新建一个id为app的div。
#touch index.html
#vi index.html
<!DOCTYPE html> 
<head> 
<title></title> 
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></script> 
</head> 
<body> 
<div id="app"></div> 
</body> 
</html>

  • 创建index.js
#touch index.js
var app=document.getElementById('app'); 
app.innerHTML="Hello My WebPack App";
  • 安装webpack开发依赖
npm install webpack –-save-dev
  • 利用webpack将index.js文件打包为bundle.js文件
./node_modules/webpack/bin/webpack.js index.js bundle.js 

  • 修改index.html文件,加入bundle.js。
<!DOCTYPE html> 
<head> 
<title></title> 
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></script> 
</head> 
<body> 
<div id="app"></div> 
<script src="bundle.js"></script> 
</body> 
</html>

  • 运行http-server,打开浏览器查看页面
http-server -p 8000

然后在浏览器打开http://localhost:8000

Demo2 - Data Update

  • 创建src和dist两个文件夹,把index.js移动到src文件夹里,bundle.js是webpack打包生成出来的,使用先删除再生成的办法确保文件正常更新,以后会把dist作为生成文件存放的目标文件夹。
  • 安装rimraf 用于打包前删除旧的生成文件。
npm install rimraf –-save-dev
  • 修改package.json的script启动方式
{
  "name": "demo1",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build":"rimraf dist && webpack src/index.js dist/bundle.js"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/fujusong/webpack-starter.git"
  },
  "keywords": [
    "webpack",
    "starter"
  ],
  "author": "sofu",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/fujusong/webpack-starter/issues"
  },
  "homepage": "https://github.com/fujusong/webpack-starter#readme",
  "devDependencies": {
    "rimraf": "^2.6.1",
    "webpack": "^2.6.1"
  }
}

  • 运行 npm run build 打包一下,在dist目录下得到了bundle.js
  • 把index.html里面引用bundle.js的路径改成./dist/bundle.js,再运行http-server。

引入Module,文件监控。

  • 接下来在src目录下新建messages.js文件
module.exports={ data:'Hello,World!', event:'APP Event'};
  • 在index.js文件引入messages.js,并实例到页面
var messages=require('./message');

var app=document.getElementById('app'); 
app.innerHTML = messages.data+"From "+ messages.event;
  • 把package.json修改一下,build的结尾加上监视命令–watch
"build":"rimraf dist && webpack src/index.js dist/bundle.js --watch"
  • 运行npm run build重新打包,可以看到打包过程并没有结束跳出,仍然是待命状态。
  • 另起一个cli,启动http-server -p 8000,在浏览器输入localhost:8000
  • 修改messages.json消息内容,然后刷新浏览器,可以看到内容随即更新了。

Demo3 - Webpack-dev-server 1

  • 安装webpack-dev-server
npm install webpack-dev-server –-save-dev
  • 创建webpack.config.js文件,并添加基本配置
var path = require('path'); // 导入路径包 

module.exports={ 
    entry:'./src/index.js',//入口文件 
    output:{ 
        path:path.join(__dirname,'dist'),// 指定打包之后的文件夹 
        publicPath:'/dist/',// 指定资源文件引用的目录 
        filename:'bundle.js'// 指定打包为一个文件 bundle.js 
    }
}
  • 打包所需的路径都已在webpack.config.js配置后,package.json的build则去掉路径,并添加webpack-dev-server启动:"dev":"webpack-dev-server"
... 
"scripts": { 
"test": "echo \"Error: no test specified\" && exit 1", 
"build": "rimraf dist && webpack --watch", 
"dev": "webpack-dev-server" 
}, 
...

  • 运行npm run dev启动webpack-dev-server进行打包,在浏览器输入localhost:8080直接打开。
  • 修改messages.json的内容,保存,可以看到浏览器实时更新了数据

Demo4 - Webpack-dev-server 2

对于webpack-dev-server,每次修改代码后,webpack可以自动重新打包,webpack-dev-server有两个用于自动刷新模式:iframe和inline,浏览器可以响应代码变化并自动刷新(hot)。

iframe

页面被嵌套在一个iframe下,代码发生改动后,iframe会重新加载
使用此模式无需额外配置,只需访问http://localhost:8080/webpack-dev-server/index.html即可,显然webpack-dev-server默认的模式就是iframe。

inline

为整个页面提供了“Live reloading”功能。webpack官方提供的一个小型Express服务器。

hot

提供了“模块热重载”功能,它会尝试仅仅更新组件被改变的部分(而不是整个页面)。会尝试先去通过 HMR 更新然后可能尝试刷新整个页面。只需要加上一个 webpack/hot/dev-server entry point,并且在 dev-server 调用时加上参数 –hot。如果我们把inline和hot这两个选项都写上,那么当文件被改动时,webpack-dev-server会先尝试HMR,如果这不管用,它就会重新加载整个页面。

hot(HMR)和inline使用有两种方式:CLI和Node.js API

CLI方式比较简单,只需修改package.json中scripts配置,添加 –inline –hot

"dev": "webpack-dev-server –inline –hot"

node.js API方式

  • 在主目录下,新建dev-server.js文件
var WebpackDevServer=require('webpack-dev-server'); 
var webpack=require('webpack'); 
var config=require('./webpack.config'); 
var path=require('path'); 
var compiler=webpack(config); 
var server=new WebpackDevServer(
    compiler,
    {//创建服务器实例 
        hot:true,//HMR配置 
        filename:config.output.filename, 
        publicPath:config.output.publicPath,//必填 
    stats:{ 
        colors:true 
        } 
    }
); 
server.listen(8080,'localhost',function(){});
  • 修改webpack.config.js配置
var path=require('path');// 导入路径包 
var webpack=require('webpack'); 
module.exports={ 
    entry:[//入口文件 
        './src/index.js', 
        'webpack/hot/dev-server',//调用热重载 hot 
        'webpack-dev-server/client?http://localhost:8080'
        //添加webpack-dev-server客户端 
    ], 
    plugins:[ 
        new webpack.HotModuleReplacementPlugin()//全局开启热代码替换 
    ], 
    output:{ 
        path:path.join(__dirname,'dist'),// 指定打包之后的文件夹 
        publicPath:'/dist/',// 指定资源文件引用的目录 
        filename:'bundle.js'// 指定打包为一个文件 bundle.js 
    } 
}
  • 在index.js最底下添加hot调用
if(module.hot){//启用热重载 
    module.hot.accept();
}
  • 修改package.json启动方式
... 
"scripts": { 
"build": "rimraf dist && webpack --watch", 
"dev": "node dev-server.js" 
}, 
...
  • 运行npm run dev ,在浏览器输入localhost:8080查看,然后尝试修改index.jsmessages.json的数据,保存,浏览器自动刷新了

Demo5 - Development and Production

在入口处区分生产环境和开发环境。

  • 修改package.json的script项,通过set NODE_ENV来设置环境变量
...
"scripts": { 
"build": "rimraf dist && set NODE_ENV=production&& webpack", 
"dev": "set NODE_ENV=development&& node dev-server.js" 
},
...
  • 修改webpack.config.js,在入口处添加NODE_ENV环境判断使用生产环境还是开发环境的入口文件及插件。process.env.NODE_ENV可以获取到启动文件的环境变量,nodejs的app.get('env')也可以取得。
var path=require('path');
var webpack=require('webpack'); 
var DEVELOPMENT=process.env.NODE_ENV==='development'; 
var PRODUCTION=process.env.NODE_ENV==='production'; 
var entry=PRODUCTION ? ['./src/index.js'] : 
[ 
    './src/index.js', 
    'webpack/hot/dev-server',//开启热重载 hot 
    'webpack-dev-server/client?http://localhost:8080' 
    //添加webpack-dev-server客户端 
]; 
var plugins=PRODUCTION ? [] : 
    [ 
        new webpack.HotModuleReplacementPlugin()
        //全局开启代码热替换 如果是CLI这里则不用写 
    ]; 
module.exports={ 
    entry:entry,//入口文件 
    plugins:plugins, 
    output:{ 
        path:path.join(__dirname,'dist'),// 指定打包之后的文件夹 
        publicPath:'/dist/',// 指定资源文件引用的目录 
        filename:'bundle.js'// 指定打包为一个文件 bundle.js 
        } 
}

3.然后分别运行npm run dev 和npm run build。

Demo6 - babel for es6/es7

  • 安装babel核心模块
npm install babel-core babel-loader babel-preset-es2015 babel-preset-stage-0 -save-dev

具体各模块的作用:

"babel-core" //转换器
"babel-loader" //转换器的加载器
"babel-preset-es2015" //ES2015转码规则
"babel-preset-stage-0" //es7支持,ES7不同阶段语法提案的转码规则(共有4个阶段),选装一个stage-0,stage-1,stage-2,stage-3


- 在项目文件添加.babelrc文件,加入转码规则

```json
{ "presets":["es2015","stage-0"]}
  • 修改webpack.config.js文件,添加module rules模块设置
...

module: { 
    rules:[ 
        { 
            test: /\.js$/, 
            use: ["babel-loader"], 
            exclude: path.resolve(__dirname, 'node_modules'),
        } 
    ] 
}
    
...
  • 在index.js中添加es6格式的方法
var messages=require('./message');
var newMessage = ()=>('<p>'+messages.data +' -From '+ messages.event+"</p>");
var app=document.getElementById('app'); 
app.innerHTML=newMessage(); 

if(module.hot){//启用热重载 
    module.hot.accept();
}
  • 运行npm run dev测试,可修改数据验证程序。

Demo7 - File Loader for Image

  • webpack.config.js的添加devtool:'source-map' ,用于在打包代码的同时生成一个sourcemap文件,并在打包文件的末尾添加//# souceURL,注释会告诉JS引擎原始文件位置

  • 在src目录内新建img文件夹,复制二张图片进来供测试用。这里使用的一张名为s1.png的小图片,大小为9k。另一张名为s2.jpg,大小191k。

  • 在src目录内新建Icon.js文件

const icon=require('./img/s1.png'); 
const Image=`![](${icon})`; 
export default Image;
  • 在src目录内新建Img.js文件
const img=require('./img/s2.jpg'); 
const Image=`![](${img})`; 
export default Image;
  • 安装文件加载器
npm install file-loader –-save-dev
  • 修改webpack.config.js文件,添加file-loader加载器
... 
module: { 
    rules:[ 
        { 
            test: /\.js$/, 
            use: ["babel-loader"], 
            exclude: path.resolve(__dirname, 'node_modules'),
        },
        {
            test: /\.(jpe?g|png)$/,
            use: ['file-loader']
        },
    ] 
},
...
  • 修改index.js,通过import加载图片到页面
import icon from './Icon'; 
import img from './Img'; 


var messages=require('./message');
var newMessage = ()=>('<p>'+messages.data +' -From '+ messages.event+"</p>");
var newMessage2=()=>(
    `<p>${icon} ${img}</p>`
); 

var app=document.getElementById('app'); 
app.innerHTML=newMessage(); 
app.innerHTML+=newMessage2();

if(module.hot){//启用热重载 
    module.hot.accept();
}

Demo8 - URL Loader for Images

使用URL Loader加载图片,limit参数可以使用base64将小图片内联在代码中,减少http请求。

  • 安装url-loader
npm install url-loader –-save-dev
  • 修改webpack.config.js,将图片的loaders改为url-loader?limit=10000&name=images/[hash:12].[ext],小于10k的图片将会以base64的形式内联在代码中,并且图片打包到images文件内,以哈希值命名。
...
module: { 
    rules:[ 
        { 
            test: /\.js$/, 
            use: ["babel-loader"], 
            exclude: path.resolve(__dirname, 'node_modules'),
        },
        {
            test: /\.(jpe?g|png)$/,
            use: ['url-loader?limit=10000&name=images/[hash:12].[ext]']
        },
    ] 
},
...

3.输入npm run dev测试,可以看到s1.png已经被base64内联。s2.jpg文件名称也变成了hash名称。

Demo9 - Add Button

  • 在src文件目录新建button.js
const Button={ 
button:'<button id="myButton">Press me</button>', 
attachEl:()=>{ 
document.getElementById('myButton').addEventListener('click',()=>{ 
// debugger; 
console.log('clicked'); 
}) 
}}; 
export default Button;
  • 修改webpack.config.js,添加dev-tool:’sourse-map’,打包代码的同时生成一个sourcemap文件。
... 
module.exports={ 
    entry:entry,//入口文件
    devtool:'source-map',//打包代码的同时生成一个sourcemap文件,并在打包文件的末尾添加souceURL注释,注释会告诉JS引擎原始文件位置 
    module: { 
        rules:[ 
            { 
                test: /\.js$/, 
                use: ["babel-loader"], 
                exclude: path.resolve(__dirname, 'node_modules'),
            }
        ] 
    }, 
... 
  • 修改index.js文件,加载button模块并实例化。
import Button from './button'; 
var newMessage=()=>(Button.button); 
var app=document.getElementById('app'); 
app.innerHTML=newMessage(); 
Button.attachEl(); 

if(module.hot){
    module.hot.accept(); 
} 
  • 运行测试,点击页面中的按钮,可以看到控制台输出了测试文字

Demo10 - compress source code

  • 修改webpack.config.js里的plugins变量,添加生产模式时加载插件。
var plugins = PRODUCTION ? [ 
    new webpack.optimize.UglifyJsPlugin(/*{//代码压缩 
        comments:true,//显示注释 
        mangle:false,//取消代码混淆 
        compress:{ 
            warnings:true//在UglifyJs删除没有用到的代码时不输出警告 
        } 
    }*/) 
    ] : [ 
            new webpack.HotModuleReplacementPlugin()//全局开启代码热替换 如果是CLI这里则不用写 
        ]; 
plugins.push( 
    new webpack.DefinePlugin({ 
        DEVELOPMENT:JSON.stringify(DEVELOPMENT), 
        PRODUCTION:JSON.stringify(PRODUCTION) 
    }) 
);
  • 修改index.js,将环境信息输出到页面
var newMessage = ()=>{
    return `DEV:${DEVELOPMENT.toString()} <br> PRO:${PRODUCTION.toString()}`;
}


var app=document.getElementById('app'); 
app.innerHTML=newMessage(); 

if(DEVELOPMENT){ 
    if(module.hot){//启用热重载 
        module.hot.accept();
    }
}

3.分别运行npm run dev 和 npm run build可以看到页面上显示的环境,再查看bundle.js,可以看到代码已经按照设置输出。

...
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "rimraf dist && NODE_ENV=production webpack && http-server -p 3000",
"dev": "NODE_ENV=development node dev-server.js"
},

...

4.回到webpack.config.js,把UglifyJsPlugin的参数都去掉,使用默认参数

var plugins=PRODUCTION ? [ 
    new webpack.optimize.UglifyJsPlugin() 
    ] : [ 
    new webpack.HotModuleReplacementPlugin()//全局开启代码热替换 如果是CLI这里则不用 写 
    ];

5.再次运行npm run build打包,此时bundle.js已经被压缩至最小化。

Demo 11 - Load CSS

  • 安装css-loader和style-loader:npm install css-loader style-loader -save-dev。
  • css-loader 在js文件里,通过require的方式来引入css
  • style-loader 在html中以style的方式嵌入css

2.在src目录下,创建style文件夹,并创建一个css文件,这里命名为:globalStyle.css

body{ 
    background:#ddd; 
}

:local(.box){ 
    background-color:#ff0; 
    padding:1em; 
    border:1px solid #000; 
}

3.在webpack.config.js添加css的loader,webpack的loader的配置是从右往左的,就是先使用css-loader之后使用style-loader

... 
module: { 
    rules:[ 
        { 
            test: /\.js$/, 
            use: ["babel-loader"], 
            exclude: path.resolve(__dirname, 'node_modules'),
        },
        {
            test: /\.css$/, 
            loaders: ["style-loader","css-loader"], 
            exclude: path.resolve(__dirname, 'node_modules'),
        }

    ] 
},
...
 
  • 修改index.js,引入css文件,并将相应的class添加进页面。
var style=require('./style/globalStyle.css'); 
const newMessage=()=>(
`<div class="${style.box}">    
    DEV:${DEVELOPMENT.toString()}<br>    
    PRO:${PRODUCTION.toString()}<br>    
</div>`

var app=document.getElementById(‘app’); 
app.innerHTML=newMessage(); 

if(DEVELOPMENT){ 
    if(module.hot){//启用热重载 
        module.hot.accept(); 
    } 
}

  • 测试页面,可以看到页面的样式已经更新,查看源码,原本div的classs为box的,已经被hash名称所代替。hash名称可以在webpack.config.js里css的加载器里自定义
...
test: /\.css$/, 
use: ["style-loader","css-loader?localIdentName=[path][name]--[local]"], 
...
  • 当需要将生产环境和开发环境命名进行区分时,可以写在一个变量或常量里
... 
const cssIdentifier=PRODUCTION? '[hash:base64:10]' : '[path][name]---[local]'; 
...
...
use: ["style-loader","css-loader?localIdentName=" + cssIdentifier], 
...
...

查看页面源码时,可以看到webpack打包时,是把样式文件以style的方式嵌在head里的

Demo12 - CSS Load Seprate

  • 安装插件用于将css样式打包成独立的文件。
npm install extract-text-webpack-plugin -save-dev
  • 需求是在开发环境样式还是嵌在页面上不变,只在打包到生产环境时,才单独打包到一个叫style.css的文件里,因此webpack.config.js里,先引入extract-text-webpack-plugin插件,然后在插件栏设置打包时的名称以及提取css加载时的路径
...
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var DEVELOPMENT=process.env.NODE_ENV==='development'; 
var PRODUCTION=process.env.NODE_ENV==='production'; 

var entry=PRODUCTION ? ['./src/index.js'] : [ 
    './src/index.js', 
    'webpack/hot/dev-server',//开启热重载 hot 
    'webpack-dev-server/client?http://localhost:8080'//添加webpack-dev-server客户端 
]; 
var plugins = PRODUCTION ? [ 
    new webpack.optimize.UglifyJsPlugin(),
    new ExtractTextPlugin('style.css'),
    ] : 
    [ 
        new webpack.HotModuleReplacementPlugin()//全局开启代码热替换 如果是CLI这里则不用写 
    ]; 
plugins.push( 
    new webpack.DefinePlugin({ 
        DEVELOPMENT:JSON.stringify(DEVELOPMENT), 
        PRODUCTION:JSON.stringify(PRODUCTION) 
    }) 
);

const cssIdentifier=PRODUCTION? '[hash:base64:10]' : '[path][name]--[local]'; 

const cssLoader=PRODUCTION ? ExtractTextPlugin.extract('css-loader?localIdentName=' + cssIdentifier) : 
    ['style-loader','css-loader?localIdentName=' + cssIdentifier];

module.exports={ 
    entry:entry,//入口文件
    module: { 
        rules:[ 
            { 
                test: /\.js$/, 
                use: ["babel-loader"], 
                exclude: path.resolve(__dirname, 'node_modules'),
            },
            {
                test: /\.css$/, 
                //use: ["style-loader","css-loader"], 
                use: cssLoader, 
                exclude: path.resolve(__dirname, 'node_modules'),
            }

        ] 
    }, 
...
  • index.html页面要单独加载打包生成的样式文件style.css
<link rel="stylesheet" href="./dist/style.css">
  • 然后运行运行npm run build 查看,此时style.css是单独生成的。

  • style.css的名称也可以用hash表示

new ExtractTextPlugin( 
'style-[contenthash:10].css'//根据内容生成hash值 
,{allChunks: true}//所有分离文件的样式也会全部压缩到一个文件上 
)

Demo13 - HTML Template

  • 安装模板插件
npm install html-webpack-plugin -save-dev

2.创建html模版:index-template.html

<!DOCTYPE html>
<head>    
<title></title>    
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>    
<div id="app"></div>
</body>
</html>
  • webpack.config.js顶部导入模版插件
var HTMLWebpackPlugin=require('html-webpack-plugin');
  • 在plugins处实例化,并将模版文件设置为index-template.html
var plugins=PRODUCTION ? [ 
    new webpack.optimize.UglifyJsPlugin(), 
    new ExtractTextPlugin( 
        'style-[contenthash:10].css'//根据内容生成hash值 
    ), 
    new HTMLWebpackPlugin({// webpack 指定目录(package内设置)生成静态HTML文件 
    template:'index-template.html' 
    }) 
] : [ 
new webpack.HotModuleReplacementPlugin()//全局开启代码热替换 如果是CLI这里则不用写
  • 静态文件在dist内生成名为index.html的文件,其他资源路径将和开发环境不同,所以需要设置区分判断。
output:{ 
path:path.join(__dirname,'dist'),// 指定打包之后的文件夹 
publicPath: PRODUCTION ? '/' : '/dist/', 
filename: PRODUCTION ? 'bundle.[hash:12].min.js' : 'bundle.js'// 指定打包为一个文件 bundle.js 
}
  • 修改package.json,运行npm run build打包测试。
...
"scripts": {
    "build": "rimraf dist && NODE_ENV=production webpack && http-server ./dist -p 3000 ",
    "dev": "NODE_ENV=development node dev-server.js"
  },

...

demo14 - Tabs Pages

  • 在src文件内新建page1.js
const page=`<h1>页面1</h1>`;
export default page;

  • 在src文件内新建page2.js
const page=`<h1>页面2</h1>`;
export default page;
  • 修改index.js,创建两个按钮,并添加相应的点击事件,事件触发时使用System导入页面并将页面的的内容复制到content内。
var app=document.getElementById('app');
app.innerHTML=`    
    <div id="menu">        
        <button id="loadPage1">Load1</button>        
        <button id="loadPage2">Load2</button>    
    </div>    
    <div id="content">        
        <h1>home</h1>    
    </div>`;
document.getElementById('loadPage1').addEventListener('click',()=>{
//System.import 会令每个可能的模块都产生一个独立的块(chunk)。    
System.import('./page1').then(pageModule=>{        
    document.getElementById('content').innerHTML=pageModule.default;    
})
});
document.getElementById('loadPage2').addEventListener('click',()=>{    
System.import('./page2').then(pageModule=>{        
    document.getElementById('content').innerHTML=pageModule.default;    
})
});

if(DEVELOPMENT){    
    if(module.hot){//启用热重载       
        module.hot.accept();    
}}
  • 运行npm ren dev测试,在这之前,别忘记把index.html引用css和js的路径改回来
  • 打开浏览器的network,来回点击按钮1和按钮2,观察network加载的内容,可以发现,0.bandle.js和1.bandle.js是异步加载,并且不会被重复加载。

Demo15 - Jquery

  • 安装jquery插件
npm install jquery –-save-dev
  • 在index.js中导入jquery,并创建一个jquery实例
import $ from 'jquery'; 
$('#app').css('background','#ff0');
  • 运行测试时,app背景已经发生改变。运行打包后,jquery也被打包进了bundle.js,这并不是我们想要的。而且,jquery并非全局,仅可在index.js使用,想要将jquery加载为全局模块,需要在webpack.config.js中设置externals
... 
module.exports={ 
    externals:{ 
        'jquery':'jQuery' 
    }, 
devtool:'source-map', 
entry:entry,//入口文件 
plugins:plugins, 
... 
  • 然后jquery需要从外部加载进来,分别添加到index.htmlindex-template.html的head中,建议使用网上的jquery的CDN。如:
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
  • 分别运行开发环境和生产环境查看,jquery从外部加载,没有被打包进bundle.js。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容