webpack(v3.*)
1、webpack介绍
webpack官网:https://webpack.js.org/
webpack中文官网:https://doc.webpack-china.org...
webpack打包工具源代码:https://github.com/webpack/we...
2、初始化项目
cd yourproject
npm init //生成package.json文件
npm install webpack --save-dev
3、webpack.config.js配置文件
(1)、context:上下文,这里省略了,默认为当前文件模块的绝对路径,下面的entry和output中的路径都是相对于context上下文的相对路径.
(2)、output属性:(v3.10.0版本要求path是绝对路径,需要使用node.js的path模块)
注意: path.resolve方法用于将相对路径转为绝对路径。
var path = require("path"); //使用前引入path模块
module.exports = {
entry: './src/js/main.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, './dist/js'),
publicPath: "https://cdn.example.com/" //用publicPath配置打包后生成线上地址
}
}
注意: publicPath,当我们需要上线的时候设置此属性,最后打包的文件路径会被替换为publicPath设置的地址值。
注意: filename: '[name]-[chunkhash].js',filename使用占位符确保每个文件具有唯一的名称。同时使用chunkhash可以达到控制文件版本号的作用,这点与gulp是相通的原理。所以,一旦文件做了修改,再执行webpack,则更改过的文件的chunkhash会发生改变,未做改动的文件的chunkhash不变。
(3)、plugins属性
介绍:plugins 是一个数组,里面是实例化的plugin,即new HtmlWepackPlugin({//code}),这种形式。
① html-webpack-plugin插件:该插件用于生成一个HTML5文件,这个文件用script标签引用所有webpack包。(https://www.npmjs.com,npm官网...
//安装
npm install html-webpack-plugin --save-dev
//webpack.config.js配置文件中引入
var HtmlWepackPlugin = require("html-webpack-plugin");
//设置配置项
plugins: [
new HtmlWepackPlugin({
filename:'index-[hash].html', //输出文件名称
template:'index.html', //模板路径
inject:"head", //值:body,head,false;script和link文件注入body或head中,或者false不注入。
chunks:["index","common"], //允许插入到模板中的一些chunk,不配置此项默认会将entry中所有的chunk注入到模板中。多页应用配置多个页面时,每个页面注入的thunk应该是不相同的,需要通过该配置为不同页面注入不同的thunk.
excludeChunks: ["constan"], //这个与chunks配置项正好相反,用来配置不允许注入的thunk。
showErrors: true, //值:true/false,默认true;是否将错误信息输出到html页面中。这个很有用,在生成html文件的过程中有错误信息,输出到页面就能看到错误相关信息便于调试。
title:"MyApp", //需要在引用template模板中调用此变量
minify: { //压缩代码
collapseWhitespace: true, //删除空格
html5: true
}
})
]
注意: title属性的坑:var HtmlWebpackPlugin = require('html-webpack-plugin'); 这个变量随意。但是在模板中<title><%= htmlWebpackPlugin.options.title %></title>必须使用驼峰式命令。不然会报错一直提示这个插件未定义。
注意: 在页面中引入inline的script方法如下:
在github上,https://github.com/jantimon/h...。共用的main.js以inline的形式引进,a.js,b.js,c.js以外链的形式引进.模板index.html中,
首先在<head>中:
<script type="text/javascript">
<%= compilation.assets[htmlWebpackPlugin.files.chunks.main.entry.substr(htmlWebpackPlugin.files.publicPath.length)].source() %>
</script>
重点:!!!compilation.assets是webpack暴露出来可以获取文件数据的方法。通过传文件名路径进这个对象,拿到这个文件的索引,通过调用source拿到文件内容。
compilation.assets需要的是不带publicPath,htmlWebpackPlugin.files.chunks.main.entry带publicPatch,所以用substr()截取。
然后在<body>中:
<%= htmlWebpackPlugin.files.chunks[k].entry %>
最后在webpack.config.js中: inject属性设置为false即可。
(4)、loader属性(以babel-loader为例,用babel-loader将js文件转义为浏览器可识别的js)
module:{
rules:[ //模块规则
{
test: /\.js$/, //正则匹配
use: [{
loader:'babel-loader',
options:{
presets: ["env"] //采用babel-loader的"env"规则将找的es6,es7,es5语法转码为浏览器可识别的js
}
}],
include: [
path.resolve(__dirname, "/src") //指定babel-loaders寻找的文件路径,注意需是绝对路径
],
exclude: [
path.resolve(__dirname, "/node_modules/") //排除node_modules文件下js,注意需是绝对路径
]
}
]
},
注意: webpack官网介绍到:“Rule.loader is a shortcut to Rule.use: [ { loader } ]”. 即下图:
(5)、loader属性(css处理的loader)(postcss参考文章:https://segmentfault.com/a/11...
在web开发中浏览器兼容问题,我们不得不使用兼容性前缀,less语言在编译时可以补全css代码的兼容性前缀,但是针对css文件不全前缀需要使用postcss-loader。如下图:
在common.css中引入其他的css文件:
在app.js入口文件中引入common.css,这样打包的时候就能将css文件进行打包:
(6)、wbpack-dev-server
//首先安装插件
npm i webpack-dev-server --save-dev
npm i cross-env --save-dev
npm i html-webpack-plugin --save-dev
package.json文件:
"scripts":{
//prod环境
"build": "cross-env NODE_ENV=production webpack --config webpack.config.js",
//dev环境
"dev": "cross-env NODE_ENV=development webpack-dev-server --config webpack.config.js"
}
webpack.config.js文件:
const path = require("path")
const HTMLWebapckPlugin = require("html-webpack-plugin")
const webpack = require('webpack') //引入webpack
//在package.json中的“NODE_ENV=development”,可通过下面的process.env读到变量NODE_ENV
const isDev = process.env.NODE_ENV === "development"
const config = {
target:"web",//web平台
entry: path.join(__dirname,'src/index.js'),
output:{
filename:'bundle.js',
path:path.join(__dirname,"dist")
},
module:{
rules:[
{
test:/\.vue$/,
loader:'vue-loader'
},
{
test:/\.css$/,
use:[
'style-loader',
'css-loader'
]
},
{
test:/\.(gif|jpg|jpeg|png|svg)$/,
use:[
{
loader:'url-loader',
options:{
limit:1024,
name:'[name]-[hash].[ext]'
}
}
]
}
]
},
plugins:[
//使用Vue、react框架时需要DefinePlugin这的插件,因为框架会根据不同环境打包依赖,所以要区分环境从而选择不同的依赖
new webpack.DefinePlugin({
//定义环境变量,对应上面的isDev判断
'process.env':{
NODE_ENV:isDev ? '"development"' : '"production"' //注意此处单引号内还需要双引号
}
}),
//生成HTML页面
new HTMLWebapckPlugin()
]
}
//dev环境
if(isDev){
//通过devtool对代码进行映射,可以在浏览器端可以调试
config.devtool = "#cheap-module-eval-sourve-map"
//devserver 是在webpack2以后才出现的
config.devServer = {
port:'8020', //端口号
host:"0.0.0.0", //设置成这样后,移动端也可以通IP访问页面
//webpack编译时任何错误显示在浏览器中
overlay:{
errors:true,
},
open:true,//自动打开浏览器
hot:true //webpack功能:不再重新刷新整个页面,而是局部更新,即热更新
}
config.plugins.push(
new webpack.HotModuleReplacementPlugin(), //搭配hot:true一起使用
new webpack.NoEmitOnErrorsPlugin() //搭配hot:true一起使用,去除一些不需要展示的信息
)
}
module.exports = config
执行npm run dev 就可以通过localhost:8020打开页面
(7)、webpack单独打包css文件
//安装依赖
npm i extract-text-webpack-plugin
在webpack.config.js文件中引用:(结合6中的配置文件)
//dev环境
if(isDev){
config.module.rules.push(
{
test:/\.scss$/,
use:[
'style-loader',
'css-loader',
{
loader:'postcss-loader',
options:{
sourceMap:true
}
},
'sass-loader'
]
}
)
config.devtool = "#cheap-module-eval-sourve-map"
//devserver 是在webpack2以后才出现的
config.devServer = {
port:'8020', //端口号
host:"0.0.0.0", //设置成这样后,移动端也可以通IP访问页面
//webpack编译时任何错误显示在浏览器中
overlay:{
errors:true,
},
open:true,//自动打开浏览器
hot:true //热更新
}
config.plugins.push(
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin()
)
}else{
//正式环境
config.output.filename='[name].[chunkhash:8].js' //正式环境使用chunkhash,dev环境不能使用chunkhash,可使用hash.
config.module.rules.push({
test:/\.scss$/,
use:ExtractTextWebpack.extract({
fallback:'style-loader',
use:[
'css-loader',
{
loader:'postcss-loader',
options:{
sourceMap:true
}
},
'sass-loader'
]
})
})
config.plugins.push(
new ExtractTextWebpack('style.[contentHash:8].css')
)
}
注意:vue组件中的css样式是不会打包到上面的style.[contentHash:8].css文件中的,因为他是异步加载的。
(8)、单独打包类库文件及hash
将类库代码和业务代码分离打包,利用浏览器长期的缓存类库代码。
//正式环境配置
{
config.entry = {
//业务逻辑代码
app:path.join(__dirname,"src/index.js"),
//类库代码在此声明,此处以Vue框架为例
vendor: ['vue']
}
config.output.filename='[name].[chunkhash:8].js',
config.module.rules.push({
test:/\.scss$/,
use:ExtractTextWebpack.extract({
fallback:'style-loader',
use:[
'css-loader',
{
loader:'postcss-loader',
options:{
sourceMap:true
}
},
'sass-loader'
]
})
}),
config.plugins.push(
new ExtractTextWebpack('style.[contentHash:8].css'),
//单独打包,app中就不会出现类库代码,必须放在runtime之前
new webpack.optimize.CommonsChunkPlugin({
//name属性值要和上面定义的vendor一致
name:'vendor'
}),
new webpack.optimize.commonsChunkPlugin({
name:'runtime'
})
)
}
hash与chunkhash区别:
hash:打包的所有文件共用的一个值
chunkhash:打包的不同的块拥有不同的chunkhash,所以正式环境应使用chunkhash,这样可以保证类库文件不会再每次更改业务重新打包后,又拥有一个新的hash值,而是一直使用之前的chunkhash,这样浏览器就不会在去下载那些依赖,从而实现了缓存。
详细请见:https://www.imooc.com/article/21538
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。