最近想学一学Webpack,在网上看了很多相关文章,但是Webpack更新的太快了,很多文章都不适用weback新的版本,我从头开始研究了一番,在这里和大家分享交流一下,有错误的地方请指出.
简介
- 从头开始搭建一个Webpack项目
- 遇到的各种警告
- 打包js文件
- 处理css文件
- 插件使用
- 提取公共js库
- webpack-dev-server 等...
一 . 搭建一个webpack项目
首先你需要一个node.js (我的版本 node v8.9.4, npm v5.6.0 )
创建一个文件夹 mkdir webpack-my
进入文件夹 cd webpack-my
创建项目 npm init
一路回车
安装webpack webpack-cli(想要执行webpack的命令必须有这个包)
--save-dev 是只添加依赖到开发环境 npm install --save-dev webpack webpack-cli
window下执行应该有几条警告 警告虽然没多大关系但我们还是来看一下WARN nomnom@1.8.1: Package no longer supported...
nomnom包过时了不用管它WARN babel-preset-es2015@6.24.1
babel推荐让使用 babel-preset-env 我们下面再安装WARN webpack-my@1.0.0 No repository field
没有仓库地址的警告可以在 npm init
命令里设置或修改package.json
:
"repository": {
"type": "git",
"url": "http://path.xxx"
}
复制代码
或者设置 "private": true
设置为私有 webpack-my@1.0.0 No description
没写描述,基本同上...
两个 WARN SKIPPING OPTIONAL DEPENDENCY: fsevents@1.1.3
fsevent是mac osx系统的,警告忽略之... (微强迫症,警告不看全不舒服...)
二 . 处理js文件
1 . 安装babel
处理js文件我们需要用到bable,先安装一下npm install --save-dev babel-loader babel-core
2 . 安装 babel-preset-env
它用来转义es6等 babel-preset-env介绍 npm install --save-dev babel-preset-env
在根目录下创建 .babelrc
文件, 加入以下代码
{
"presets": ["env"]
}
复制代码
3 . 解决浏览器兼容及性能问题
为防止浏览器不支持 Promise/Object.assign/Array.from等还有性能问题,我们引入两个包:
- babel-polyfill babel-polyfill介绍
- babel-plugin-transform-runtime babel-plugin-transform-runtime介绍
npm install --save-dev babel-polyfill babel-plugin-transform-runtime
引入生产版本依赖 npm install --save babel-runtime
通过 .babelrc
添加配置
{
"presets": [
"env"
],
"plugins": [
"transform-runtime"
]
}
复制代码
babel-polyfill
需要在 webpack中配置下面会说到
4 . 让我们来配置一下webpack :
创建 src
/bundle
文件夹作为我们存放/生成代码的地方
创建 webpack.config.js
文件作为webpack的配置文件 path
为node.js内置的,用来处理路径的, __dirname
是node.js的全局属性,代表当前路径。
将 babel-polyfill 加到你的 entry 数组中使用
配置js文件要经过babel转义
const path = require('path');
module.exports = {
//entry为入口,webpack从这里开始编译
entry: [
"babel-polyfill",
path.join(__dirname, './src/index.js')
],
//output为输出 path代表路径 filename代表文件名称
output: {
path: path.join(__dirname, './bundle'),
filename: 'bundle.js'
},
//module是配置所有模块要经过什么处理
//test:处理什么类型的文件,use:用什么,include:处理这里的,exclude:不处理这里的
module: {
rules: [
{
test: /\.js$/,
use: ['babel-loader'],
include: path.join(__dirname , 'src'),
exclude: /node_modules/
}
]
},
};
复制代码
好了让我们来试验一下,在src
里创建 text-0.js
text-1.js
text-2.js
index.js
内容分别为:
export const Text0 = "小明";
复制代码
export const Text1 = "在公司";
复制代码
export const Text2 = "写代码";
复制代码
import {Text0} from './text-0.js';
import {Text1} from './text-1.js';
import {Text2} from './text-2.js';
const textFun = (...arg) => {
let P = document.createElement("p");
P.innerHTML = arg.join(" ");
document.getElementById('root').appendChild(P);
}
textFun(Text0,Text1,Text2);
复制代码
5 . 使用webpack
控制台输入 npx webpack --config webpack.config.js
npx是什么
根据webpack.config.js打包文件
等等出现了什么 WARNING in configuration The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/
原来是让我们设置开发或者生产模式
在 webpack.config.js
里设置
mode: 'development'
复制代码
为了方便使用我们在 package.json
里加入webpack打包的命令方便我们使用修改 script
项
"scripts": {
"build": "npx webpack --config webpack.config.js"
},
复制代码
这样再次运行我们直接输入 npm run build
js文件打包好了,让我们创建一个html页面看看效果吧,在bundle
文件夹下创建 index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
</head>
<body>
<div id='root'></div>
<script type="text/javascript" src="./bundle.js" charset="utf-8"></script>
</body>
</html>
复制代码
注意在这里写了一个script标签引入 bundle.js
打开html文件看看效果吧
如果你想看看打包出来的js文件,你可以在
webpack.config.js
里添加
devtool
属性
属性配置
图简单的话直接配置
devtool: ''
就可以了.
三 . 处理less文件
1 . 安装处理 css 相关 loader
npm install --save-dev css-loader style-loader
css-loader
让你能import css , style-loader
能将css以style的形式插入
2 . 安装 less 相关
npm install --save-dev less less-loader
3 . 安装 postcss
和 postcss-cssnext
添加浏览器前缀
npm install --save-dev postcss-loader postcss-cssnext
创建 postcss.config.js
加入以下代码
module.exports = {
plugins: {
'postcss-cssnext': {}
}
}
复制代码
我在这里尝试 autoprefixer
插件但是好像不管用,可能还依赖别的包.
4 . 配置webpack
在 webpack.config.js
-> module
-> rules
里添加配置
处理顺序从右到左 less
-> postcss
-> css
-> style
{
test: /\.less$/,
use: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader']
}
复制代码
四 . 插件
1 . 生成HTML插件
安装插件npm install --save-dev html-webpack-plugin
配置 webpack.config.js
const htmlWebpackPlugin = require('html-webpack-plugin');
...
plugins: [
new htmlWebpackPlugin({
filename: "index.html", //打包后的文件名
template: path.join(__dirname , "./src/index.html") //要打包文件的路径
})
],
复制代码
在 src
文件夹里创建一个 index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
</head>
<body>
<div id='root'></div>
</body>
</html>
复制代码
html-webpack-plugin用法全解
删除 bundle
文件夹下所有文件
重新运行 npm run build
看看效果吧
2 . 生成CSS插件
安装插件(目前必须有@next) npm install --save-dev extract-text-webpack-plugin@next
添加配置 webpack.config.js
const ExtractTextPlugin = require('extract-text-webpack-plugin');
...
module: {
rules: [
...
{
test: /\.less$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ['css-loader', 'postcss-loader', 'less-loader']
})
}
]
},
plugins: [
...
new ExtractTextPlugin({
filename: 'index.css'
}),
],
复制代码
3 . 清理打包文件插件
上述代码所打出的包名称一直是一样的,很容易造成缓存问题
我们在 webpack.config.js
中做一下修改 outoup
下的 filename: 'bundle.js'
为 filename: 'bundle.[hash:8].js'
plugins
-> ExtractTextPlugin
下的 filename: 'index.css'
为 filename: 'index.[hash:8].css'
缓存的问题解决了,但是我们每次生成的都是不同名字的文件 bundle
文件夹里的东西越来越多,我们需要一个插件来清理它.
安装插件 npm install --save-dev clean-webpack-plugin
修改 webpack.config.js
const CleanWebpackPlugin = require('clean-webpack-plugin');
...
plugins: [
...
new CleanWebpackPlugin(['bundle'])
]
复制代码
====== 2018.09.26 update ======
4 . 代码压缩件插件
npm install uglifyjs-webpack-plugin -D
安装代码压缩插件
修改 webpack.config.js
const uglify = require('uglifyjs-webpack-plugin');
...
plugins: [
...
new uglify()
]
复制代码
五 . 提取公共js
在 webpack.config.js
里添加
output: {
...
chunkFilename: '[name].[chunkhash:8].js'
},
...
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'common',
chunks: 'all'
}
}
}
},
复制代码
参考文章 webpack4 splitChunksPlugin && runtimeChunkPlugin 配置杂记
六 . webpack-dev-server配置
安装 webpack-dev-server
npm install --save-dev webpack-dev-server
webpack.config.js
添加配置
...
devServer: {
contentBase: path.join(__dirname, 'bundle'), //启动路径
host:'localhost', //域名
port: 8018, //端口号
}
复制代码
执行命令 npx webpack-dev-server --config webpack.config.js
为了方便使用添加 package.json
中,加入 --color(颜色) --progress(进度) --hot(热加载)
"scripts": {
"build": "npx webpack --config webpack.config.js",
"start": "npx webpack-dev-server --config webpack.config.js --color --progress --hot"
},
复制代码
七 . 编译图片
npm install --save-dev url-loader file-loader
webpack.config.js
-> rules
增加配置:
{
test: /\.(png|jpg|gif)$/,
use: [{
loader: 'url-loader',
options: {
limit: 8192 //8k一下的转义为base64
}
}]
}
复制代码
总结
到这里一个拥有基础功能的webpack包就建好了,后续有什么想到的东西我会继续更新...
以后可能会加上React , 项目的代码放在我的github
第一次写文章,有什么问题请告诉我~
====== 2018.5.13 update ======
笔者回来慢慢填坑了
八 . CSS Modules 使用
使用 CSS Modules
来模块化我们的CSS 修改我们的 webpack.config.js
-> module
-> rules
{
test: /\.less$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
- use: ['css-loader', 'postcss-loader', 'less-loader'],
+ use: ['css-loader?modules&localIdentName=[local]-[hash:base64:5]', 'postcss-loader', 'less-loader']
})
}
复制代码
这样我们所有经过 rules
的 less
名字都被加了hash了
在我们的 index.less
中加入
.module-test{
background-color: green;
color: blue;
}
复制代码
对应我们在 index.js
中加入
//替换之前的引入
import style from './index.less';
const textFun = (...arg) => {
let P = document.createElement("p");
P.innerHTML = arg.join(" ");
+ P.className = style["module-test"];
document.getElementById('root').appendChild(P);
}
复制代码
运行 npm run build
好了我们遇到一个问题,之前写的 #root
也被 CSS Modules 改变了 可是我们的 #root
是写在 index.html
里的
我们把 #root
改成这样 :global(#root)
这样就不会被改变了.
====== 2018.5.20 update ======
后续暂时没什么时间继续更新文章了(想开新坑...)。
我做了一些关于多页面打包、公共库提取、公共代码提取的配置
在我的 github 里
欢迎来访,同时求个star 求个Fork
====== 2018.07.15 update ======
热加载设置 webpack.config.js
中的 devServer
加入 hot: true
entry
入口添加 webpack/hot/only-dev-server
开启热加载
需要热加载的页面加入
if (module.hot) {
module.hot.accept();
}
复制代码
开启热加载
注意这种配置在多页面情况下只有首页可以热模块加载 其他的页面不行
====== 2018.07.16 update ======
加上 source-map
能看清楚错误在哪个文件 devtool: 'source-map'