一、webpack3.x.x基本介绍
1-1 webpack基本介绍
webpack的概念和作用
模块打包器
代码分割
代码文件打包
loader加载
commonjs规范
模块热更新
适用于大型项目1-2 webpack安装和命令
安装
npm install webpack --save-dev
例子:
新建hello.js执行命令 webpack hello.js hello.bundle.js ,会生成hello.bundle.js文件,观察文件中的内容,可以看到webpack在文件中生成了许多其他代码
新建world.js并在hello.js文件中require('./world.js'),再执行命令webpack hello.js hello.bundle.js,观察hello.bundle.js文件中的内容
新建style.css,在样式表中随便新建几行样式html,body{background: #f00;},在hello.js文件中require('style-loader!css-loader!./style.css'),执行命令webpack hello.js hello.bundle.js(注意:用webpack加载css需要用到css-loader,行内样式需要用到style-loader。安装loader npm install css-loader style-loader --save-dev)
css-loader用来将style.css打包到hello.bundle.js文件中,使webpack能处理.css文件,如果将css-loader处理后的文件,引入到页面中后(在这个例子中引入页面的是hello.bundle.js),style-loader则会将style.css中的样式以<style></style>的形式插入到head中
如果在页面中没有加载这两个loader也可以在命令行中直接加载loader webpack hello.js hello.bundle.js --module-bind "css=style-loader!css-loader"
输入webpack可以查看webpack中有哪些配置项
webpack hello.js hello.bundle.js --watch 用来监听文件,如果文件有变化则自动编译打包
webpack hello.js hello.bundle.js --progress 用来查看打包的进度
webpack hello.js hello.bundle.js --display-modules 用来查看打包的模块
webpack hello.js hello.bundle.js --display-resons 用来查看打包的原因
二、webpack基本配置
- 2-1建立项目的webpack配置
例子:
在webpack-demo目录下新建以下文件
webpack-demo
-dist
--js
-src
--script
--style
-index.html
-package.json
-webpack.config.js
webpack.config.js
module.exports = {
entry: './src/script/main.js',//入口文件
output: {
path: './dist/js',//输出路径
filename: 'bundle.js'//输出文件名
}
}
运行 webpack 会在dist下的js目录下生成bundle.js
可在package.json的script字段中添加配置webpack
"scripts": {
"webpack":"webpack --config webpack.config.js --progress --display-modules --colors --display-reasons"
},
- 2-2
webpack配置的entry和output
entry是入口文件
①entry可以是一个字符串
entry:'a.js'
{
context: __dirname + "/app",
entry: "./entry",
output: {
path: __dirname + "/dist",
filename: "bundle.js"
}
}
②entry可以是一个数组
数组中的文件一般是有相互依赖关系的,或者是没有互相依赖关系但是又处于某些原因需要将它们打包在一起
entry:['a.js','main.js']
③entry可以是一个对象({key:value})常用于多页面(多入口)的情况下配置
key
key可以是简单的字符串,比如:’app’, ‘main’,’entry-1’等。并且对应着output.filename配置中的[name]变量key还可以是路径字符串。此时webpack会自动生成路径目录,并将路径的最后作为[name]。这个特性在多页面配置下也是很有用的
entry: {
'path/of/entry': './deep-app.js',
'app': './app.js'
},
output: {
path: './output',
filename: '[name].js'
}
value
value如果是字符串,而且必须是合理的node require函数参数字符串。比如文件路径:’./app.js’(require(‘./app.js’));比如安装的npm模块:’lodash’(require(‘lodash’))
value如果是数组,则数组中元素需要是上面描述的合理字符串值。数组中的文件一般是没有相互依赖关系的,但是又处于某些原因需要将它们打包在一起。比如:
output: {
path: _dirname+'/built',//输出路径
filename: '[name].js'//输出文件名
filename: '[name]-[hash].js'//输出文件名
filename: '[name]-[chunkhash].js'//输出文件名
}
entry:{
page1:'./page1'
page2:['entry1.js','entry2.js']
}
在entry是多入口的情况下,output也应该是多个输出 filename有三个可选参数 [name]、[hash]、[chunkhash]
output: {
path: _dirname+'/built',//输出路径
filename: '[name].js'//输出文件名
}
注意,在不同的版本下可能会报路径不是绝对路径的错误,解决办法为
var path = require('path');
module.exports = {
entry: [url('src/script/main.js'), url('src/script/a.js')],
output: {
path: url('./dist/js/'),
filename: 'bundle.js'
}
}
function url(url) {
return path.resolve(__dirname, url)
}
三、生成项目中的html文件
- 3-1自动化生成项目中的html文件(上)
安装
html-webpack-plugin(这里有个坑就是,如果在全局安装webpack,在运行npm run webpack之前需要运行 npm link webpack)
自动生成html的意义在于,html中引用的js文件好多都是webpack打包之后生成的,生成的文件名和目录都有可能改变,这个时候不能手动来修改每一个变动的路径,太耗时,这个时候就要通过html-webpack-plugins这个插件来自动在html中生成对js的引用
在webpack.config.js中加入plugins配置项
var htmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
main: './src/script/main.js',
a: './src/script/a.js'
},
output: {
path: './dist',
filename: 'js/[name]-[hash].js'
},
plugins: [
new htmlWebpackPlugin({
template:'index.html',
inject:'head'
})
]
}
在htmlWebpackPlugin插件中配置项template用来定义引用的模板文件,inject用来指定脚本在dom文档中的插入位置
- 3-2自动化生成项目中的html文件(中)
template应用场景
在参数中传参,在模板中引用
plugins: [
new htmlWebpackPlugin({
template:'index.html',
inject:'head',
filename:'index-[hash].html',
title:'webpack is good'//传参
date:new Date()//传参
})
]
在html的title中,以如下的方式引用
<title><%= htmlWebpackPlugin.options.title %></title>
<%= htmlWebpackPlugin.options.title %>这种方式的引用在模板中的任何一个位置都可以,例如
plugins: [
new htmlWebpackPlugin({
template:'index.html',
inject:'head',
title:'webpack is good'
date:new Date()
})
]
<body>
<%= htmlWebpackPlugin.options.date %>
</body>
这样在编译后的index.html文件中会包含日期信息Tue Apr 04 2017 23:25:58 GMT+0800 (中国标准时间)
在html文件中body标签中,输入如下代码,运行 npm run webpack
<% for(var key in htmlWebpackPlugin){ %>
<%= key %>
<% } %>
生成的文件中会有files options,这两个值说明在htmlWebpackPlugin插件中存在这两个对象
继续遍历htmlWebpackPlugin.files htmlWebpackPlugin.options这两个对象
<% for(var key in htmlWebpackPlugin.files){ %>
<%= key %>:<%= JSON.stringify(htmlWebpackPlugin.files[key])%>
<% } %>
<% for(var key in htmlWebpackPlugin.options){ %>
<%= key %>:<%= JSON.stringify(htmlWebpackPlugin.options[key])%>
<% } %>
得到
//files
publicPath:""
chunks:{"main":{"size":27,"entry":"js/main-c6074c5f07c44041cf45.js","hash":"ddd0a31267a8793ca2d8","css":[]},"a":{"size":14,"entry":"js/a-c6074c5f07c44041cf45.js","hash":"ef609b383ce569e49d38","css":[]}}
js:["js/main-c6074c5f07c44041cf45.js","js/a-c6074c5f07c44041cf45.js"]
css:[]
manifest:
//options
template:"F:\\localhost\\wamp\\www\\webpack-demo\\node_modules\\._html-webpack-plugin@2.28.0@html-webpack-plugin\\lib\\loader.js!F:\\localhost\\wamp\\www\\webpack-demo\\index.html"
filename:"index.html"
hash:false
inject:"head"
compile:true
favicon:false
minify:false
cache:true
showErrors:true
chunks:"all"
excludeChunks:[]
title:"webpack is good"
xhtml:false
date:"2017-04-04T15:45:55.712Z"
//压缩
minify:{
removeComments:true,//删除注释
collapseWhitespace:true//删除空格
}
可以用<%= %>这种灵活的方式实现更多的个性化定制
- 3-3自动化生成项目中的html文件(下)
多文件形式/多页面应用
var htmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
main: './src/script/main.js',
a: './src/script/a.js',
b: './src/script/b.js',
c: './src/script/c.js'
},
output: {
path: './dist',
filename: 'js/[name]-[hash].js'
},
plugins: [
new htmlWebpackPlugin({
filename:'main.html',
template: 'index.html',
title: 'webpack is main',
date: new Date()
}),
new htmlWebpackPlugin({
filename:'a.html',
template: 'index.html',
title: 'webpack is a',
date: new Date()
}),
new htmlWebpackPlugin({
filename:'b.html',
template: 'index.html',
title: 'webpack is b',
date: new Date()
}),
new htmlWebpackPlugin({
filename:'c.html',
template: 'index.html',
title: 'webpack is c',
date: new Date()
})
]
}
chunks用来指定匹配的生成文件中应该生成数组中的文件(excludeChunks和chunks相反)
var htmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
main: './src/script/main.js',
a: './src/script/a.js',
b: './src/script/b.js',
c: './src/script/c.js'
},
output: {
path: './dist',
filename: 'js/[name]-[hash].js'
},
plugins: [
new htmlWebpackPlugin({
filename:'main.html',
template: 'index.html',
title: 'webpack is main',
date: new Date(),
chunks:['a','b','c']
}),
new htmlWebpackPlugin({
filename:'a.html',
template: 'index.html',
title: 'webpack is a',
date: new Date(),
chunks:['b','c']
}),
new htmlWebpackPlugin({
filename:'b.html',
template: 'index.html',
title: 'webpack is b',
date: new Date(),
chunks:['a','c']
}),
new htmlWebpackPlugin({
filename:'c.html',
template: 'index.html',
title: 'webpack is c',
date: new Date(),
chunks:['a','b']
})
]
}
main.html中会生成 a.js b.js c.js
a.html中会生成b.js c.js
b.html中会生成a.js c.js
c.html中会生成a.js b.js
将生成的脚本变成内联脚本
compilation.assets[htmlWebpackPlugin.files.chunks.main.entry].source()
如果在申明publicPath的情况下代码应该是这样
compilation.assets[htmlWebpackPlugin.files.chunks.main.entry.substr(htmlWebpackPlugin.files.publicPath.length)].source()
htmlWebpackPlugin.files.publicPath.length 得到publicPath的长度例如 https://www.baidu.com
htmlWebpackPlugin.files.chunks.main.entry.substr()得到文件真实路径
最后用compilation.assets[].source()得到内容
在main.js已经以内联的方式插入到文档,那么多后续的出来main.js则不需要任何操作,可以在index.html里面写入这样的模板语法,来判断是否是main.js以外的文件,如果不是则插入
四、处理项目中的资源文件
- 4-1什么是
loader以及loader的特性
加载器是应用于模块源代码的转换。它们允许您在导入或“加载”它们时预处理文件。因此,加载器就像是其他构建工具中的“任务”,并提供了一种强大的方法来处理前端构建步骤。加载器可以将文件从不同的语言(如打字稿)转换为JavaScript,或者将内联图像转换为数据url。加载器甚至允许您直接从JavaScript模块导入CSS文件
有3种使用loader的方式
1. 在webpack.config.js文件中指定
module: {
rules: [{
test: /\.css$/,
use: [{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
modules: true
}
}]
},
{
test: /\.jsx?$/,
include: [path.resolve(__dirname, "app")],
exclude: [path.resolve(__dirname, "app/demo-files")],
issuer: {
test,
include,
exclude
},
enforce: "pre",
enforce: "post",
loader: "babel-loader",
options: {
presets: ["es2015"]
},
},
{
test: /\.html$/,
use: [
// apply multiple loaders and options
"htmllint-loader", {
loader: "html-loader",
options: {}
}]
},
]
}
- 在每个import语句中显式地指定它们
require('style-loader!css-loader!./style.css')
import Styles from 'style-loader!css-loader?modules!./styles.css' 在命令行中使用
webpack --module-bind 'css=style-loader!css-loader'
webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'- 4-2使用babel-loader转换ES6代码
npm install –save-dev babel-loader babel-core babel-preset-env
cnpm install --save-dev babel-loader babel-core babel-preset-es2015
cnpm install babel-preset-env --save-dev
webpack-demo
-dist
-node_modules
-src
--components
---layer
----layer.html
----layer.js
----layer.css
--app.js
-index.html
-package.json
-webpack.config.js
const htmlWebpackPlugin=require('html-webpack-plugin');
const path = require('path');
module.exports={
entry:'./src/app.js',
output:{
path:__dirname+'/dist',
filename:'[name].bundle.js'
},
module:{
rules:[
{
test:/\.js$/,
include:path.resolve(__dirname, "src"),
exclude: path.resolve(__dirname, "node_modules"),
use:{
loader: "babel-loader",
options:{
"presets": [
"es2015"
]
}
}
}
]
},
plugins:[
new htmlWebpackPlugin({
title:'app',
inject:'head',
template:'index.html',
filename:'index.html',
minify:{
collapseWhitespace:true
}
})
]
}
presets:['latest']也可以放在package.json文件中
"babel":{
"presets": [
"es2015"
]
}
或者放在.babelrc中
{
"presets": [
"es2015"
]
}
注意,webpack目前只在您的node_modules文件夹中搜索加载器。如果这些加载器是在您的node_modules文件夹之外定义的,那么您需要使用resolveLoader属性来获得webpack来包含您的loader。例如,假设您的自定义加载器包含在一个名为loaders的文件夹中。您需要在配置文件中添加以下内容:
resolveLoader: {
modules: ['node_modules', path.resolve(__dirname, 'loaders')]
}
path.resolve(__dirname+''),用来将相对路径改为绝对路径
cnpm install --save-dev babel-preset-latest
cnpm install --save-dev babel
注意:在webpack2.0中 有些不一样
module: {
rules: [
{
test: /\.js$/,
use: 'babel-loader',
exclude: path.resolve(__dirname + 'node_modules'),
include: path.resolve(__dirname + 'src'),
query: {
presets: ['env']
}
}
]
}
注意:加入include配置项会导致babel不处理es6语法,原因暂不明
- 4-3处理项目中的css
postcss-loader
autoprefixer是postcss-loader的一个子集
postcss用在css-loader和style-loader之后,用在sass|less|stylus-loader之前
module: {
rules: [{
test:/\.js$/,
include:__include,
exclude: __exclude,
use:{
loader: "babel-loader",
options:{
"presets": [
"es2015"
]
}
}
},
{
test: /\.css$/,
use: [
'style-loader',
{loader:'css-loader', options: {importLoaders: 1}},
{
loader: 'postcss-loader',
options: {
plugins: function() {
return [
require('autoprefixer')
];
}
}
}
]
}
]
}
注意:
1. loader的执行顺序从右向左
2. style-loader!css-loader?importLoaders=1!postcss-loader
3. ?importLoaders=1是css-loader后面的参数,意思是在css-loader后指定一个处理import样式的命令
- 4-4使用less和sass
sass-loader less-loader
npm install sass-loader node-sass webpack --save-dev
sass-loader依赖node-sass和webpack
{
test:/\.scss$/,
use:[
'style-loader',
{loader:'css-loader', options: {importLoaders: 1}},
{
loader:'sass-loader'
},
{
loader: 'postcss-loader',
options: {
plugins: function() {
return [
require('autoprefixer')
];
}
}
}
]
}
- 4-5处理模板文件
html-loader
{
test:/\.html$/,
loader:'html-loader'
}
ejs-loader
{
test:/\.tpl$/,
loader:'ejs-loader'
}
- 4-6处理图片及其他文件
file-loader url-loader用来处理图片
url-loader和fileloader差不多,但是可以指定limit参数,当图片大小,小于limit时由url-loader处理成base64,当图片大小大于imit时就由file-loader处理成路径
image-webpack-loader用来压缩图片
在模版中使用相对路径图片的方法
${require('../../assets/bg.png')}
var htmlWebpackPlugin = require('html-webpack-plugin');
var path = require('path');
module.exports = {
entry: {
"main": __dirname + '/src/script/main.js',
"a": __dirname + '/src/script/a.js',
"b": __dirname + '/src/script/b.js',
"c": __dirname + '/src/script/c.js',
},
output: {
filename: 'js/[name]-[hash].js',
path: __dirname + '/dist',
},
module: {
rules: [{
test: /\.js$/,
loader: 'babel-loader',
exclude: path.resolve(__dirname + 'node_modules'),
query: {
presets: ['env']
}
},
{
test: /\.css$/,
use: [
'style-loader',
{
loader:'css-loader',
options:{
importLoaders:1
}
},
{
loader: 'postcss-loader',
options: {
plugins: function() {
return [
require('autoprefixer')
];
}
}
}
]
}
]
},
plugins: [
new htmlWebpackPlugin({
filename: 'main.html',
template: 'index.html',
inject: false,
title: 'webpack is main.html',
date: new Date(),
excludeChunks: ['a', 'b']
}),
new htmlWebpackPlugin({
filename: 'a.html',
template: 'index.html',
inject: false,
title: 'webpack is a.html',
date: new Date(),
excludeChunks: ['b', 'c']
}),
new htmlWebpackPlugin({
filename: 'b.html',
template: 'index.html',
inject: false,
title: 'webpack is b.html',
date: new Date(),
excludeChunks: ['a', 'c']
}),
new htmlWebpackPlugin({
filename: 'c.html',
template: 'index.html',
inject: false,
title: 'webpack is c.html',
date: new Date(),
excludeChunks: ['a', 'b']
})
]
}
const htmlWebpackPlugin=require('html-webpack-plugin');
const path = require('path');
const __include=path.resolve(__dirname, "src");
const __exclude=path.resolve(__dirname, "node_modules");
module.exports={
entry:'./src/app.js',
output:{
path:__dirname+'/dist',
filename:'[name].bundle.js'
},
module:{
rules:[
{
test:/\.js$/,
include:__include,
exclude: __exclude,
use:{
loader: "babel-loader",
options:{
"presets": [
"es2015"
]
}
}
},
{
test:/\.html$/,
loader:'html-loader'
},
{
test: /\.css$/,
use: [
'style-loader',
{loader:'css-loader', options: {importLoaders: 1}},
{
loader: 'postcss-loader',
options: {
plugins: function() {
return [
require('autoprefixer')
];
}
}
}
]
},
{
test:/\.scss$/,
use:[
'style-loader',
{loader:'css-loader', options: {importLoaders: 1}},
{
loader:'sass-loader'
},
{
loader: 'postcss-loader',
options: {
plugins: function() {
return [
require('autoprefixer')
];
}
}
}
]
}
]
},
plugins:[
new htmlWebpackPlugin({
title:'app',
inject:'body',
template:'index.html',
filename:'index.html',
minify:{
collapseWhitespace:true
}
})
]
}
1万+

被折叠的 条评论
为什么被折叠?



