摘要
这篇文章讲述了,如何用webpack + ES6/7 + sass 进行组件化开发,最后生产出兼容的压缩好的 css,js 文件。
先说一下简单的使用
下面例子用的是 webpack4.1.0,不同版本的 webpack 可能会稍有不同。
首先创建一个目录 webpack-test,并cd到目录
第一步:初始化npm,会写入一个package.json的文件
npm init
第二步:安装 webpack
//当前目录中安装webpack
npm i -D webpack
第二步:安装Webpack-cli
//当前目录中安装
npm i -D webpack-cli
第五步:构建文件
目录结构如下
|-- dist // 项目编译打包目录
|-- src // 项目源文件
|-- main.js // 程序入口文件,加载各种公共组件
|--common //公共组件文件夹
|--scss //sass组件
main.scss //
|--js //js组件
|-- bar.js // bar组件
|-- static // 静态文件目录
|-- reset.css //css文件
|-- webpack.config.js // webpack配置文件
|-- index.html // 入口html文件
|-- package.json // 项目及工具的依赖配置文件
|-- package-lock // npm版本控制
inex.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>webpack</title>
</head>
<body>
<div id="app">
</div>
<script src="./dist/bundle.js"></script>
</body>
</html>
reset.css
*{
margin: 0;
padding: 0;
}
main.scss
#app div{
font-size: 40px;
color: red;
}
bar.js
export function createDiv(str) {
let div = document.createElement('div');
div.innerHTML = str;
return div;
};
export function add(str1,str2) {
return str1 + str2;
};
main.js
import '../static/css/reset.css';
import './common/js/main.scss';
import { createDiv, add } from './common/js/bar.js';
let sum = add('你好啊, ','webpack');
document.querySelector('#app').appendChild(createDiv(sum));
第六步: 安装css-loader
npm i -D style-loader css-loader
第七步:配置 webpack.config.js
const path = require('path');
module.exports = {
entry: './src/app.js',
output: {
path: path.resolve(__dirname, './dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
// 用正则去匹配要用该 loader 转换的 CSS 文件
test: /\.css$/,
use: [
'style-loader',
'css-loader'
],
}
]
}
};
第八步配置 packjson.json
在scripts中加入了下面这一句,这样就可以用 npm run build
来启动目录下的 webpack 了。development
是指输入开发环境的代码,改为production
则为生产环境的代码,即压缩好的。
"build": "webpack --mode development"
{
"name": "webpack-test",
"version": "1.0.0",
"description": "\"第一个webpack测试\"",
"main": "index.js",
"scripts": {
"build": "webpack --mode development",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "dean",
"license": "ISC",
"devDependencies": {
"css-loader": "^0.28.10",
"extract-text-webpack-plugin": "^3.0.2",
"style-loader": "^0.20.2",
"webpack": "^4.1.0",
"webpack-cli": "^2.0.10"
}
}
第九步:运行webpack,将项目打包
npm run build
然后你就会看到在dist文件夹下生成了 bundle.js,在浏览器中打开index.html就可以看到效果了。
第十步:DevServer 的使用
安装
npm i -D webpack-dev-server
此时 index.html
中的 script:src 要改为bundle.js。因为这个服务器生成的bundle.js是在内存中的
<script src="bundle.js"></script>
然后在 package.json
文件中的scripts中添加
"start": "webpack-dev-server --watch --mode production",
然后启动
npm run start
然后就可以在 localhost:8080 中看到实时预览了。不过这个功能有点坑爹,有时候的效果会不正确。
Loader&&Plugin
前面讲了 webpack 的基本使用,下面再来讲讲常用的 Loader
和 Plugin
。
在一般开发中,我们会想让 webpack 帮我们自动处理一些类似于把 es6
转为 es5
这样的事情,这时候就需要使用loader
和plugin
。
经常要用到的 loader
和plugin
如下 :
sass
首先全局中安装
npm i -g node-sass
接入webpack
## 安装 webpack loader 依赖
npm i -D sass-loader css-loader style-loader
## sass-loader 依赖 node-sass
npm i -D node-sass
postcss
npm i -D postcss-loader
## postcss支持下一代css
## autoprefixer自动补全前缀
npm i -D postcss-cssnext
npm i -D autoprefixer
这个装完还需要在首目录创建一个文件postcss.config.js
module.exports = {
plugins: [
require('autoprefixer')({
browsers: ['last 10 Chrome versions', 'last 5 Firefox versions', 'Safari >= 6', 'ie > 8']
}),
require('postcss-cssnext')
]
};
ES6
平常写 es6
的时候都要用babel转为 es5
。webpack 也可以帮你完成。
npm i -D babel-plugin-transform-runtime
# Webpack 接入 Babel 必须依赖的模块
npm i -D babel-core babel-loader
# 根据你的需求选择不同的 Plugins 或 Presets
npm i -D babel-preset-env
在目录首页创建 .babelrc
文件,内容大致如下,env
表示包含最新版本的所有新特性,更多参数见官方文档
{
"presets": [
["env", { "modules": false }]
],
"plugins": ["transform-runtime"],
"comments": false
}
url-loader,file-loader
当要在sass里加载图片时,就需要使用 url-loader 和 file-loader。
url-loader是对file-loader的上层封装。设置limit,这样体积小于limit的图片将直接以base64的形式内联在代码中,可以减少一次http请求。
npm i -D url-loader
npm i -D file-loader
配置webpack.config.js
{
test:/\.(png)|(jpg)$/,
use: ['url-loader?limit=8192&name=img/[name].[ext]']
}
extract-text-webpack-plugin
有时我们需要在打包的时候把css文件单独抽离出来,这时候就需要用到 extract-text-webpack-plugin
。
暂时来说我找不到什么办法可以让 webpack4.1.0
使用这个插件,所以我先把webpack降回到3.1.0版本。
这时 package.json 文件中的 stripts 中的 mode=production 要删去,因为这是webpack4的写法。
npm i -D webpack@3.1.0
npm i -D extract-text-webpack-plugin
然后配置webpack.config.js
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module: {
rules: [
{
// 用正则去匹配要用该 loader 转换的 CSS 文件
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback:'style-loader',
use:[{'css-loader?minimize&?sourceMap'},'postcss-loader?sourceMap' ]
}),
},
]
},
plugins:[
new ExtractTextPlugin('css/main.css')
]
这样就可以把css文件在打包的时候单独抽离出来了,再在html文件中link这个文件即可。
minimize
是打包的时候 把css 文件压缩。
sourceMap
是生成转换地图,方便调试。
CleanWebpackPlugin
有时候我们会反复打包多次,在 dist
文件夹下就可能会有多余文件,所以就需要用到这个插件,在每次打包之前先清空 dist
文件夹。或清除指定格式的文件。
npm i -D clean-webpack-plugin
配置如下:
const CleanWebpackPlugin = require('clean-webpack-plugin');
plugins:[
new CleanWebpackPlugin(
['dist/*',], //匹配删除的文件
{
root: __dirname, //根目录
verbose: true, //开启在控制台输出信息
dry: false //启用删除文件
}
),
]
webpack.optimize.UglifyJsPlugin
这个插件是webpack自带的,不需要单独安装。
总结
上述所有 loader
和 plugin
一次性安装。用的 cnpm
是淘宝镜像,装的比较快。这次装的是 webpack@3.1.0
npm init
cnpm i -D webpack@3.1.0 style-loader css-loader sass-loader node-sass postcss-loader postcss-cssnext autoprefixer url-loader file-loader babel-plugin-transform-runtime babel-core babel-loader babel-preset-env extract-text-webpack-plugin webpack-dev-server clean-webpack-plugin
最终的 webpack.config.js
配置如下:
const path = require('path');
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
// 用正则去匹配要用该 loader 转换的 CSS 文件
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback:'style-loader',
use:['css-loader?minimize&?sourceMap','postcss-loader?sourceMap' ]
}),
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback:'style-loader',
use:['css-loader?minimize&?sourceMap', 'postcss-loader?sourceMap' ,'sass-loader?sourceMap']
}),
},
{
test: /\.js$/,
use: ['babel-loader'],
exclude: [/node_modules/]
},
{
test:/\.(png)|(jpg)|(jpeg)|(gif)$/,
use: ['url-loader?limit=8192&name=img/[name].[ext]']
}
]
},
plugins:[
new CleanWebpackPlugin(
['dist/*',], //匹配删除的文件
{
root: __dirname, //根目录
verbose: true, //开启在控制台输出信息
dry: false //启用删除文件
}
),
new ExtractTextPlugin({
filename:`main.css`,
}),
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
warnings: false
}
})
],
devtool: 'source-map',
};`
.babelrc
{
"presets": [
["env", { "modules": false }]
],
"plugins": ["transform-runtime"],
"comments": false
}
postcss.js
module.exports = {
plugins: [
require('autoprefixer')({
browsers: ['last 10 Chrome versions', 'last 5 Firefox versions', 'Safari >= 6', 'ie > 8']
}),
require('postcss-cssnext')
]
};
这样配置完毕之后,我们就可以使用 ES6/7 + sass 去写项目,最终用 webpack 去打包,压缩,就可以生成兼容的页面了。如果用的是 Vue 或 Rect 则修改 一些参数即可。