webpack基本配置
写于2018-10-23,基于webpack 4.22.0写的demo
项目文件放在github上
安装
npm install -g webpack 全局安装
搭建项目
-
在项目文件夹创建package.json文件,里面包括当前项目的基本信息,依赖模块,自定义的脚本任务等。使用npm init命令可以自动创建这个package.json文件。
-
本项目中安装webpack
npm install -D webpack
- 在本项目中安装webpack-cli
npm install -D webpack-cli
- 创建一个app文件夹用来存放项目代码,创建一个public文件夹用来存放webpack打包后的js文件
- 在public文件夹中创建index.html作为项目的主页面入口,引入打包后的js文件bundle.js
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>webpack4Demo</title> </head> <body> <h1>webpack4 Demo</h1> <div id="app"></div> <script src="bundle.js"></script> </body> </html>
- 在app文件夹中创建页面demo.js,组件component.js和数据component.json
配置打包命令行
在package.json中对scripts对象进行相关设置即可
"scripts": {
"dev": "webpack --mode development",//开发模式,打包后的代码不压缩
"build": "webpack --mode production",//生产模式,打包后的代码压缩
"package": "webpack --progress --watch --hot"
},
只有start命令可以直接用npm start运行,其他命令需要npm run {script name}如npm run build
progress是显示打包进程,watch是监听文件变化,hot是启动热加载(更多命令)
配置webpack
-
在项目根目录新建webpack.config.js配置文件,有了这个文件,项目打包时会自动引用webpack.config.js文件中的配置选项。webpack4.x中webpack.config.js这样的配置文件不是必须的。
-
打包出入口
entry: __dirname + "/app/demo.js" //“__dirname”是node.js中的一个全局变量,它指向当前执行脚本所在的目录 output: { path: __dirname + "/public", //打包后的文件存放的地方 filename: "bundle.js" //打包后输出文件的文件名 },
默认入口文件是./src/index.js,默认输出文件./dist/main.js。
-
生成Source Maps(使调试更容易)
devtool: 'eval-source-map',
eval-source-map适用于小到中性项目,对输出的js文件的执行具有性能安全隐患,适合开发阶段使用
cheap-module-eval-source-map方法构建速度更快,但是不利于调试,推荐在大型项目考虑时间成本时使用。
-
使用webpack构建本地服务器
npm install --save-dev webpack-dev-server //安装依赖,这个本地服务器基于node.js构建
在webpack.config.js文件中配置:
devServer: { contentBase: "./public", //本地服务器所加载的页面所在的目录 port: "5999", //设置默认监听端口,如果省略,默认为”8080“ inline: true, //实时刷新 historyApiFallback: true //在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true,所有的跳转将指向index.html },
在package.json文件中配置:
"scripts": { "server": "webpack-dev-server --open" // --open自动打开浏览器窗口 },
-
Loaders的配置
通过使用不同的loader,webpack有能力调用外部的脚本或工具,实现对不同格式的文件的处理;
Loaders的配置(在module.rules中配置多个 loader):
-
test:一个用以匹配loaders所处理文件的拓展名的正则表达式(必须)
-
loader:loader的名称(必须)
-
include/exclude:手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)(可选)
-
options(query):为loaders提供额外的设置选项(可选)
常用loaders:
-
babel-loader 加载 ES2015+ 代码,然后使用 Babel 转译为 ES5
npm install --save-dev @babel/core babel-loader @babel/preset-env 安装babel相关依赖包
module.exports = { module: { rules: [{ test: /\.jsx?/, // 支持 js 和 jsx include: [ path.resolve(__dirname, 'app'), // app目录下的才需要经过 babel-loader 处理,path.resolve()将路径转化为绝对路径 ], loader: 'babel-loader', }], }, }
-
@babel/preset-react 解析react的JSX语法
npm install --save-dev @babel/preset-react --save-dev 安装依赖包
module: { rules: [ { test: /(\.jsx|\.js)$/, //一个用以匹配loaders所处理文件的拓展名的正则表达式(必须) use: { loader: "babel-loader", //loader的名称(必须) options: { presets: ["@babel/preset-react", "@babel/preset-env"] } }, exclude: /node_modules/ //include/exclude:手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)(可选); } ] }
-
babel可使用单独的配置文件
在根目录新建.babelrc文件,webpack会自动调用.babelrc里的babel配置选项
// .babelrc文件 { "presets":["@babel/preset-react", "@babel/preset-env"] }
-
处理css样式表
css-loader使你能够使用类似@import 和 url(…)的方法实现 require()的功能;
配置css-loader,使css模块,把CSS的类名传递到组件的代码中,这样做有效避免了全局污染;
style-loader将所有的计算后的样式加入页面中;
二者组合在一起使你能够把样式表嵌入webpack打包后的JS文件中。
npm install --save-dev style-loader css-loader 安装依赖包
{ test: /\.css$/, use: [ { loader: "style-loader" },{ loader: "css-loader", options: { modules: true, // 指定启用css modules localIdentName: "[name]__[local]--[hash:base64:5]" // 指定css的类名格式 } } ] }
-
css预处理器(sass,less)
less:npm install --save-dev less-loader less 安装依赖包
sass:npm install --save-dev sass-loader node-sass 安装依赖包
为CSS代码自动添加适应不同浏览器的CSS前缀:postcss-loader 和 autoprefixer(自动添加前缀的插件)
npm install --save-dev postcss-loader autoprefixer 安装依赖包
在webpack配置文件中添加postcss-loader,在根目录新建postcss.config.js并添加如下代码
module.exports = { plugins: [ require('autoprefixer') ] };
-
处理图片文件
npm install --save-dev file-loader url-loader 安装依赖包
file-loader与url-loader的区别:url-loader可以设置图片大小限制,当图片超过限制时,其表现行为等同于file-loader,而当图片不超过限制时,则会将图片以base64的形式打包进css文件,以减少请求次数。
{ test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: 'img/[name].[hash:7].[ext]', publicPath:"/dist/" }, } // 或者 { test: /\.(png|jpg|gif)$/, use: [{ loader: 'file-loader', options: {}, }], }
-
-
插件(Plugins)
- 压缩js代码使用uglifyjs-webpack-plugin,不需要安装,webpack内置插件。
- 添加版权申明插件,不需要安装,webpack内置插件。
const webpack = require('webpack'); //在webpack.config.js中引入webpack plugins: [ new webpack.BannerPlugin('版权所有,翻版必究') ]
-
单独打包css使用extract-text-webpack-plugin
-
关联HTML使用html-webpack-plugin(参考文章)
作用是依据一个简单的index.html模板,生成一个自动引用你打包后的JS文件的新index.html。这在每次生成的js文件名称不同时非常有用(比如添加了hash值)。
npm install --save-dev html-webpack-plugin 安装
新建模板页面temp.html放在public文件夹内
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>webpack4Demo</title> </head> <body> <h1>webpack4Demo</h1> <div id="app"></div> </body> </html>
修改webpack.config.js内的相关配置
const HtmlWebpackPlugin = require('html-webpack-plugin'); //引入插件 // ··· output: { //修改打包后的位置 path: __dirname + "/dist", //打包后的文件存放的地方 filename: "index_bundle.js" //打包后输出文件的文件名 }, // ··· plugins: [ new HtmlWebpackPlugin({ filename: 'index.html', // 配置输出文件名和路径 template: __dirname + '/public/temp.html', // 配置文件模板 }) ]
-
Hot Module Replacement模块热替换(参考文章)
使我们能够在修改组件代码后,不用刷新整个页面,而是局部替换掉部分模块代码并使其生效,可以看到代码变更后的效果。webpack-dev-server就是一个HMR插件。
-
配置publicPath:
当使用html-webpack-pulgin的时候,publicPath是不用配置的,它会把生成的js, css 自动插入到生成的index.html中
如果不使用html-webpack-pulgin,配置devServer.publicPath与output.publicPath保持一致
-
配置devServer.hot为true
-
引入插件new webpack.HotModuleReplacementPlugin(),不需要安装,webpack内置插件
-
引入new webpack.NamedModulesPlugin()插件,显示模块相对路径。
-
在入口文件设置:
if (module.hot) { module.hot.accept(() => { render( // <BrowserRouter> // <Hello /> // </BrowserRouter>, // document.getElementById('app') ); }) }
-
如果需要保存状态的热更新插件react-hot-loader
webpack-dev-server的热更新对于保存react状态是无法做到的
- 安装cnpm install --save-dev react-hot-loader
- 在babel添加配置:“plugins”: [“react-hot-loader/babel”]
- 添加entry参数:”react-hot-loader/patch“
- 修改主入口文件:
//引入插件 import { AppContainer } from 'react-hot-loader'; if (module.hot) { module.hot.accept(() => { render( <AppContainer> <BrowserRouter> <Hello /> </BrowserRouter> </AppContainer>, document.getElementById('app') ); }) }
-