最近在看webpack,因为是第一次用,迷迷糊糊的,从安装到使用的过程中,是一路遇坑.后面才知道webpack已经更新到4.2的版本了,里面某些用法和之前3.x的差别还是很大,而我看的一些资料中是3.x的用法,导致了不能正常使用.
好在一通搜索和不断尝试后,现在坑填的差不多了.记录一下, 帮自己巩固下记忆,也希望能帮到遇到同样问题的小伙伴们.
直接在命令行工具中输入
npm install webpack -g
安装完成后,通过输入 webpack -v 来验证下是否正确安装.
在4.0以下的版本中,是可以直接通过webpack ./src/index.js ./dist/bundle.js 来将源文件index.js打包到bundle.js文件的,但是当我输入后,却提示我”webpack-cli未安装”,在网上搜索后才知道,4.0之前的是将cli及webpack安装在一个包的,但4.0之后是安装在不同包,所以要分别下载.这里要注意的是,最好将webpack-cli全局安装,因为局部安装后,某些地方还是无法识别webpack(教训之谈啊…).
原以为安装好后,就可以愉快的使用上面的那行命令将文件打包的,但是一运行,已经报错,这次的提示是 module not found:can’t resolve … (懵)
直接抛出最后的结论: 在4.0及以上版本中,不能使用之前的那行命令了,要打包文件,必须先去配置好webpack.config.js文件,配置完成后,直接在命令行中输入webpack即可.
还是上面那个例子,现在在配置文件中写入
var path = require('path');
module.exports = {
entry : './src/index.js' , //入口文件
output:{ //输出文件目录及文件名
filename: 'bundle.js',
path:path.resolve(__dirname,'./dist')
}
};
因为4.0中默认输出的文件夹是./dist,所以如果项目中也是要将输出存放于./dist的话,可以不写最后一句.
注意,这里__dirname是两个下划线组成,我最开始时没注意,写的一个下划线,就提示 _dirname is not defined.后面把文档的代码copy下来一个个对照着,才发现了问题.
webpack loader可以理解为将某一类文件进行特定处理.像css-loader将css转换为可在js文件中引用的模块,babel-loader将es6代码转换为es5及以下代码,sass-loader将文件转换为css. 这里以css-loader为例,css-loader通常与style-loader配合使用.
先去安装相应的包
npm i css-loader --save-dev
npm i style-loader --save-dev
–save-dev 参数是为了在package.json中写入依赖,这样别人看代码时,可以一下就知道项目依赖了哪些包.
配置文件中加入
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader','css-loader']
}
]
}
这里是参考官网文档
配置好了后,直接打开任意js文件,在其中将css引入就可以了.有一个地方要注意的是,官网的配置文档里是这种写法,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
modules: true
}
}
]
但不知道为什么,我通过这种配置构建后,css文件并没有被引入,(持续懵),后面是改成上面的写法才构建成功的.所以如果有小伙伴也出现这样的问题,不妨换下写法试试.
webpack plugin即完成loader完成不了的事,像压缩js,压缩图片,分离css等.要说的是,在之前压缩js,都是通过使用UglifyJS的,但通过几次webpack使用,我发现每次打包好的文件已经被压缩了,所以我猜想4.0之后的应该是自动压缩文件了的.
但仍然提一下UglifyJS,我们可以直接npm下载一个,也可以使用webpack内置的.使用内置的时,要注意,之前的webpack是全局安装的,但如果要用这个插件,需要在本地再安装一次.然后在配置文件中写入
var webpack = reqiure('webpack');
plugins: [
new webpack.optimize.UglifyJsPlugin(),
]
这里再列出几个常用插件.
1.html-webpack-plugin
它是一个html模板插件,使用了它,我们就不用手动去添加html文件中需要用到的js文件了.配置如下,
var HtmlWebpackPlugin = require('html-webpack-plugin');
new HtmlWebpackPlugin({template :'./src/index.html',
filename : 'index.html'
})
这里要特别注意的是,html-webpack-plugin要使用的话,必须要在本地安装webpack,然后在配置文件中将其reqiure,否则的话就会报一系列乱七八糟的错误,无法生成index.html(我也不知道为什么>-<,就这个解决方法还是试了好久才出来的…).
2.copy-webpack-plugin
这个插件可以帮我们把某些文件复制到指定的地方,像我们需要把当前src/images中的图片复制到dist/images下,就可以使用这个插件.配置如下,
const CopyWebpackPlugin = require('copy-webpack-plugin');
new CopyWebpackPlugin([{
from: __dirname + '/src/images',
to : __dirname +'/dist/images'
}])
这个是最基础的配置,其他复杂的可以参考官方文档.
联系这两天使用1,2插件过程中出现的问题,这里顺便说下,当我们使用html-webpack-plugin 插件构建的html页面,发现看到的效果不是在src/index.html中的效果,打开控制台,会看到关于图片404 not found的提示,这时不要慌,是因为新的html文件中图片指向的路径不存在,这时用copy-webpack-plugin插件把图片拷过来就ok啦.
3.webpack-dev-server
当下载到本地,在配置文件中require后,开启服务器,
webpack-dev-server --open
它会自动打开一个页面,在本地看到html运行效果(前提是安装了html-webpack-plugin).同时,它是一直自动构建的,当我们将源代码修改,保存后,会即时的反应到页面中.
这里也有需要注意的地方,因为4.0后webpack-cli是单独存放在一个包的,而这个server运行的时候,需要用到cli,所以还要单独下载webpack-cli(貌似如果webpack没有的话,也需要单独下载到本地).
(ps:之前我一直有个疑惑,这个插件会将修改即时反应,而hot-module-replacement也是即时反应,它们两者的区别是什么呢? 后面通过大神的解释,才知道它们的区别.
webpcak-dev-server是会即时刷新页面,但它不会保留上一步操作的状态,而HMR则会将模块进行替换,保证了应用状态不会丢失,这在测试中很有帮助 )
这里有一个注意的地方是,启动 webpcak-dev-server 后,webpack 编译不会在 dist 目录下生成本地文件,而是在保存在内存中。这会导致压缩插件 UglifyJsPlugin 找不到本地文件而报错,所以在运行 webpcak-dev-server 前要把 UglifyJsPlugin 的配置去掉.在代码完全写好后,将原dist目录删掉,重新打包一次.
4.clean-webpack-plugin
之前是每次构建之后,如果src中内容有需要修改的地方,则要在修改后,删除dist目录,然后重新构建一次,这样确实麻烦了.通过clean-webpack-plugin插件,每次修改后直接webpack,它会自动将之前的dist目录删除,重新构建的.配置如下,
const CleanWebpackPlugin = require('clean-webpack-plugin');
new CleanWebpackPlugin(
['./dist'],
{
root:__dirname,
verbose:true,
dry:false
}
),
这里也有一个需要补充的地方,虽然webpack是能智能识别插件的执行顺序,但为了代码的维护性,通常还是将clean-webpack-plugin放在第一项.
5.extract-text-webpack-plugin
这个插件可以帮我们把把一些特定的文件提取出来,像从js中把css文件单独提取出来.这里要注意的是,webpack4.0以上还没有升级这个插件,所以直接安装这个版本,会报错,Use Chunks.groupsIterable and filter by instanceof Entrypoint instead,所以这里需要再另外安装一个版本,
npm i extract-text-webpack-plugin@4.0.0-beta.0 --save-dev
这样的话,就可以正常使用了.配置如下,
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module: {
rules: [{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
}]
},
new ExtractTextPlugin("styles.css"),
哦,对了,这个插件也需要webpack的依赖,所以如果没有本地安装,也需要特意安装写webpack在本地.
在使用这个插件时,如果我们也安装了html-webpack-plugin,则在构建完成之后,会自动把添加到html中的,没有这个插件,我们则需要手动加入.虽说将css单独提出来后会增加http请求及配置复杂等,但它的优点在于能并行请求css,减少DOM操作,运行时间更快.总的来说,优点大于缺点.
这里推荐两篇博客,一篇里面列了一些常用插件,另一篇是Webpack 3.X - 4.X 升级记录,从这里可以找到一些错误的解决方法.
本来只想记录下填的坑,写的过程中不觉把自己对webpack的一些理解及常用工具都加上了.不过这些都还是一些很基础的用法,还要不断填坑学习啊…