一、理解Webpack的打包过程
1.创建一个test目录并进入
mkdir test && cd test
- npm 初始化,生成package.json文件
npm init -y //如果不加-y就一路回车
- 安装webpack
npm install webpack --save-dev //会安装到test目录下node_modules目录下面
4.在根目录下新建一个hello.js文件并用webpack进行打包
touch hello.js
./node_modules/.bin/webpack hello.js hello.bundle.js
这样就完成了一次最简单的打包,./node_modules/.bin/webpack就是安装在test目录下的webpack命令。虽然完成了一次极简的打包,但是这样是远远不够的。
5.试着多添加一个world.js文件
world.js
export { world } //写一个函数并将它暴露出来
function world() {
alert('我是world')
}
hello.js内容
require('./world.js') //引入world.js
world() 在hollo.js中执行world.js中的函数
运行打包命令
./node_modules/.bin/webpack hello.js hello.bundle.js
成功打包。这样,hello.js就是入口文件,其它文件诸如world.js都通过ES6/Commom.js/AMD语法引入到这个入口文件里,然后打包成一个文件hello.bundle.js文件。这样,就可以实现模块化编程,不仅仅是JS文件,CSS、SASS、LESS、VUE等都可以引入到入口文件里,再进行打包,这就是模块化,而需要做的,就是安装针对不同类型的loader。
二、配置文件
上面写的内容主要是理解,接下来为了更好地发挥webpack的功能,我们重新整理和配置webpack的文件
1. 删除之前根目录下除了node_modules和json文件之外的所有其它文件。
2. 在test目录下新建src目录,所有的源码都放在这里,在src目录下,分别新建script目录和style目录用来存放
js文件和样式文件。
3. 在test目录下新建dist目录,作为打包以后的输出文件的存放目录。
4. 在test目录下新建index.html文件,用script标签引入dist/bundle.js文件。
5. 在test目录下新建webpack.config.js作为配置文件。
三、配置webpack.config.js
webpack.config.js是webpack的配置文件,在我们运行webpack打包命令的时候,它会自动去寻找这个文件,然后根据这个文件里的具体配置来进行打包。
- webpack.config.js内容
var path = require('path') //引入path
module.exports = { //注意这里是exports不是export
entry: './src/script/main.js', //入口文件
output: { //输出文件
path: path.resolve(__dirname,'dist'), //输出文件的目录
filename: 'bundle.js' //输出文件的名称
}
}
运行打包命令
./node_modules/.bin/webpack //有了配置文件以后直接输入命令即可,它会自动找配置文件
如果我们有多个配置文件,比如还有一个webpack.dev.config.js文件,webpack默认运行的文件是webpack.config.js,但是想要让它运行另一个配置文件应该怎么办呢?办法如下:
./node_modules/.bin --config webpack.dev.config.js //使用--config参数就行了
这里还有一个问题,就是每次运行webpack命令,都要写./node_modules/.bin/webpack这样一长串,可不可心简化呢?当然是可以的。只需要package.json文件里写一个script就行了。
这样,只要我们运行npm build
就相当于执行了webpack命令,而npm会非常智能地从node_modules里找这个命令。
当然,这个命令还可以继续优化。我们发现,每次打包以后,bundle.js的文件都会非常大,如果让它变小呢?那就使用./node_modules/.bin/webpack -p
这个命令 -p就是出版的意思,这样它就会自动压缩,所以我再改一下package.json文件。
这样,再次运行npm run build
就相当于运行了./node_modules/.bin/webpack -p
了。我们可以明显地发现,bundle.js的体积被压缩了。
- 运行打包命令时可以使用的其它参数
./node_modules/.bin/webpack --progress --display-modules --display-reason --colors //看到过程、显示模块、显示打包原因、看到颜色变化
四、多页面进行打包时webpack.config.js的配置方法
var path = require('path')
module.exports = { //注意这里是exports不是export
entry: { //这里entry写成了对象,这样的话就可以写多个入口文件分别打包
main: './src/script/main.js',
a: './src/script/a.js'
},
output: {
path: path.resolve(__dirname,'dist'),
filename: '[name]-[hash]-bundle.js' //这里[name]-[hash]-bundle.js通过name和hash来区分不同的
}
}
这样的话,就可以把多个入口文件打包成不同文件名和不同哈希值的JS文件,并且都放在dist目录下。
但是这里却有一个很大的问题,那就是每次打包都会新生成一次打包文件,这些文件如何放到HMTL里呢?总不能每打一次包就手动更改一次吧?为了解决这个问题,就需要使用一个插件:html-webpack-plugin。用这个插件动态生成HTML文件并且把相应的打包文件放到里面。
npm安装插件
npm install html-webpack-plugin --save-dev
改写webpack.config.js文件:
var path = require('path')
var HtmlWebpackPlugin = require('html-webpack-plugin') //Common.js语法引入插件
module.exports = { //注意这里是exports不是export
entry: {
main: './src/script/main.js',
a: './src/script/a.js'
},
output: {
path: path.resolve(__dirname,'dist'),
filename: '[name]-[hash]-bundle.js'
},
plugins: [ //使用插件
new HtmlWebpackPlugin({ //因为要生成两个不同的html文件,所以要new两次
filename: 'index.html', //filename指定生成html文件名
template: 'index.html', //template指定打包参照的模板
chunks: ['main'] //chunks参数指定要把哪个入口文件打包后嵌入到HTML里,可以是一个也可以是多个
}),
new HtmlWebpackPlugin({
filename: 'a.html',
template: 'a.html',
chunks: ['a']
})
]
}
运行打包命令后,我们可以看到在dist目录下,生成两个打包的JS文件和HTML文件,而打开a.html里面就内嵌了a开头的打包的js文件。而参照的template就是根目录下index.html和a.html文件。
五、使用loaders来加载资源(这一部分很重要)
webpack可以将各种各样的资源,包括CSS/SASS/LESS/PNG/JPG/JPEG等都进行打包,只是它需要应用不同的loader。
安装loaders
npm install --save-dev babel-loader babel-core babel-preset-es2015 //这是将es6转换为es5所必须的
npm install --save-dev postcss-loader css-loader style-loader autoprefixer cssnano //安装相应loader和插件
npm install --save-dev less less-loader //安装less和less-loader
npm install --save-dev sass sass-loader //安装sass和sass-loader
npm install --save-dev file-loader url-loader
在使用postcss-loader的时候有点复杂,先在要目录下新建一个postcss.config.js文件,如下:
module.exports = {
plugins: { //这里可以使用各种各样的插件,postcss非常强大
'autoprefixer': {}, //这个插件用来给CSS文件添加前缀
'cssnano': {} //这个插件用来压缩CSS
}
}
在webpack.config.js的配置文件配置loader:
var path = require('path')
var HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = { //注意这里是exports不是export
entry: {
main: './src/script/main.js',
a: './src/script/a.js'
},
output: {
path: path.resolve(__dirname,'dist'),
filename: '[name]-[hash]-bundle.js'
},
module: {
loaders: [ //loaders在这里
{ test: /\.js$/, //针对js文件里可能出现的es6语法转换
exclude: path.resolve(__dirname, 'node_modules'), //不检测的路径,这里用path改为了绝对路径
include: path.resolve(__dirname, 'src'), //检测的路径,注意这里是绝对路径,写相对路径会报错。
loader: 'babel-loader',
query: {
presets: ['es2015'] //这个参数可以写在这里,也可以在根目录下建一个.babelrc或者写在package.json里
}
},
{
test:/\.css$/,
use: [ //这里写法和上面不太一样,但是效果相同
{loader: 'style-loader' }, //效果依然是从右往左,先是postcss-loader
{loader: 'css-loader', options: {importLoaders: 1}}, //这个css-loader写了一个参数,是为了让@import 进来的CSS也同样可以通过postcss-loader
{
loader: 'postcss-loader',
options: {
plugins: (loader) => [
require('autoprefixer')({ broswers: ['last 5 versions'] }), //这里给插件添加参数
require('cssnano')()
]
}
}
]
},
{
test: /\.less$/,
loader: 'style-loader!css-loader!postcss-loader!less-loader' //这里postcss-loader必须放在less和css之间
},
{
test: /\.scss$/,
loader: 'style-loader!css-loader!postcss-loader!sass-loader'
},
{
test: /\.(jpg|png|gif|svg$)/, //对于一些图片文件的加载,可以使用file-loader和url-loader
use: [ //对于CSS中的url可以正常加载没问题,对于组件里的就需要用到require语法
{ //如果是在根目录index.html那个img的话,那就没办法了,要么转换成背景图片,要么就使用import导入到入口的JS文件里,再用JS方法加上去
// loader: 'file-loader',
loader: 'url-loader', //url-loader和file-loader的区别在于,可以指定一个limit参数,小于它就用base-64位编码
options: {
limit: 200000,
// name: 'images/[name].[ext]',
}
}
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
chunks: ['main']
}),
new HtmlWebpackPlugin({
filename: 'a.html',
template: 'a.html',
chunks: ['a']
})
]
}
对于index.html里图片url路径的问题,要么转化成背景图片,要么import到入口JS文件里再用JS的办法添加,其它没有办法。