Webpack 入门
如果你不想一步一步的学习,也可以直接从头到尾的阅读一遍,然后直接去将案例下载下来,假设有不懂的可以再回来看一遍.
前言
-
什么是Webpack
Webpack 可以看做是模块打包机 : 它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss, TypeScript等), 并将其转换和打包为合适的格式供浏览器使用.
-
WebPack和Grunt以及Gulp相比有什么特性
其实Webpack和另外两个并没有太多的可比性,Gulp/Grunt是一种能够优化前端的开发流程的工具,而WebPack是一种模块化的解决方案,不过Webpack的优点使得Webpack在很多场景下可以替代Gulp/Grunt类的工具。
Grunt和Gulp的工作方式是:在一个配置文件中,指明对某些文件进行类似编译,组合,压缩等任务的具体步骤,工具之后可以自动替你完成这些任务。
Webpack的工作方式是:把你的项目当做一个整体,通过一个给定的主文件(如:index.js),Webpack将从这个文件开始找到你的项目的所有依赖文件,使用loaders处理它们,最后打包为一个(或多个)浏览器可识别的JavaScript文件。
Webpack的处理速度更快更直接,能打包更多不同类型的文件。
-
一切皆模块
Webpack 有一个优点, 它把所有的文件都当作模块处理, JavaScript代码, Css 和 fonts 以及图片等等通过合适的loader都可以被处理.
模块化开发使得开发者把浮渣的代码转化为小的, 干净的, 依赖声明明确的单元, 配合优化工具, 依赖管理 和加载管理可以自动完成
准备
-
创建 package.json 文件
npm init
-
安装 Webpack 作为依赖包
npm install --save-dev webpack
-
构建项目结构
创建 app 文件夹, 用来存放原始数据和我们将要写的JavaScript模块
创建 public 文件夹, 用来存放之后供浏览器读取的文件 (包括使用 webpack 打包生成的js件以及一个 index.html文件)
再创建三个文件: public/index.html , app/Greeter.js , app/main.js
-
写入基础代码
我们在index.html文件中写入最基础的html代码,它在这里目的在于引入打包后的js文件
<!-- index.html --> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Webpack Sample Project</title> </head> <body> <div id='root'></div> <script src="bundle.js"></script> </body> </html>
我们在Greeter.js中定义一个返回包含问候信息的html元素的函数,并依据CommonJS规范导出这个函数为一个模块:
// Greeter.js module.exports = function() { var greet = document.createElement('div'); greet.textContent = "Hi there and greetings!"; return greet; };
main.js文件中我们写入下述代码,用以把Greeter模块返回的节点插入页面。
//main.js const greeter = require('./Greeter.js'); document.querySelector("#root").appendChild(greeter());
开始使用Webpack
-
在根目录下新建一个名为
webpack.config.js
的文件.module.exports = { entry: __dirname + "/app/main.js", //唯一入口文件路径 output: { path: __dirname + "/public", //打包后的文件存放路径 filename: "bundle.js" //打包后输出文件的文件名 } }
__dirname
是 node.js 的一个全局变量, 它指向当前执行脚本所在的目录 -
修改 package.json 文件的配置
虽然它不是必需的,但是这样可以更快捷的执行我们的打包任务,配置后只要使用
npm start
命令就可以直接的执行打包任务了{ "name": "demo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "start": "webpack" <= 修改的是这里 }, "author": "Lling", "license": "ISC", "devDependencies": { "webpack": "^4.3.0" } }
这里需要知道的是:
-
package.json
中的script
会按照一定顺序寻找命令对应的位置 -
npm 中的
start
命令是一个特殊的脚本名称,其特殊性表现在, 命令行中使用npm start
就可以执行其对应的命令, 如果对应的此脚本名称不是start
, 想要在命令行中运行时, 需要这样用 :npm run {scrpit name}
.例如:npm run build
-
如果
npm start
报错,那么你可以试试安装一下webpack-cli
npm install webpack-cli -D
-
Webpack 的强大功能
生成Source Maps (使调试更容易)
对小到中型的项目 ,推荐配置 eval-source-map
,需要强调的是只应该在开发阶段使用它
// webpack.config.js
module.exports = {
devtool: 'eval-source-map',
entry: __dirname + "/app/main.js",
output: {
path: __dirname + "/public",
filename: "bundle.js"
}
}
构建本地服务器
监听代码的修改, 并且自动刷新显示修改后的结果
-
安装 webpack-dev-server 依赖
npm install --sava-dev webpack-dev-server
-
添加配置
module.exports = { devtool: 'eval-source-map', entry: __dirname + "/app/main.js", output: { path: __dirname + "/public", filename: "bundle.js" }, devServer: { port: 8082, // 设置默认监听端口, 如果省略 ,默认为 8080 inline: true, // 设置为true, 当源文件改变时会自动刷新页面 contentBase: "./public", // 默认会为根文件夹提供本地服务器. 这里设置'public'目录为服务器所加载的页面目录 historyApiFallback: true, // 如果设置为true, 所有的跳转将指向 index.html (开发单页面时非常游泳) } }
-
在 package.json 文件上添加配置以开启本地服务器
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "webpack", "server": "webpack-dev-server --open" }
现在
npm run server
就可以在设置的相应端口上查看结果啦!
Loaders
通过使用不同的loader, webpack有能力调用外部的脚本或工具,实现对不同格式的文件处理, 比如说分析转换 scss 为css, 或者把下一代的js文件(es6,es7)转换为现代浏览器兼容的js文件等
在webpack.config.js
中的modules
关键字下的配置说明
参数 | 说明 | 备注 |
---|---|---|
test | 一个用以匹配loaders所处理文件的扩展名的正则表达式 | 必须 |
loader | loader的名称 | 必须 |
include / exclude | 手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹) | 可选 |
在使用前我们先修改一下我们的文件
// config.json
{
"greetText": "Hi there and greetings from JSON!"
}
// Greeter.js
var config = require('./config.json');
module.exports = function() {
var greet = document.createElement('div');
greet.textContent = config.greetText;
return greet;
};
Babel
Babel其实就是一个编译JavaScript的平台. 它可以让你使用最新的JavaScript代码(es6, es7),而不用管新标准是否被当前使用的浏览器完全支持; 让你能使用基于JavaScript进行了拓展的语言,比如React的JSX
-
Babel 的安装与配置
Babel其实是几个模块化的包,其核心功能位于称为babel-core的npm包中,webpack可以把其不同的包整合在一起使用,对于每一个你需要的功能或拓展,你都需要安装单独的包(用得最多的是解析Es6的babel-env-preset包和解析JSX的babel-preset-react包)。
先一次性安装这些依赖包
// npm一次性安装多个依赖模块,模块之间用空格隔开 npm install --save-dev babel-core babel-loader babel-preset-env babel-preset-react
在 webpack 中配置Babel的方法如下:
module.exports = { devtool: 'eval-source-map', entry: __dirname + "/app/main.js", output: { path: __dirname + "/public", filename: "bundle.js" }, devServer: { contentBase: "./public", historyApiFallback: true, inline: true }, module: { rules: [ { test: /(\.jsx|\.js)$/, use: { loader: "babel-loader", options: { presets: [ "env", "react" ] } }, exclude: /node_modules/ } ] } };
现在webpack的配置已经允许我们使用es6以及jsx的语法了, 你可以开始尝试使用看看
-
Babel 的配置
其实Babel完全可以在
webpack.config.js
中进行配置,但是考虑到babel具有非常多的配置选项, 因此为了让配置文件看起来不至于太复杂,我们将其提取出来.分成两个配置文件进行配置 (webpack 会自动调用.babelrc
里的babel配置选项)// webpack.config.js module: { rules: [ { test: /(\.jsx|\.js)$/, use: { loader: "babel-loader" }, exclude: /node_modules/ } ] }
//.babelrc { "presets": ["react", "env"] }
CSS处理
-
样式表处理. webpack 提供两个工具处理样式表,
css-loader
和style-loader
.css-loader
使你能够使用类似@import
和url(...)
的方法实现require()
的功能style-loader
将所有的计算后的样式加入页面中npm install --save-dev style-loader css-loader
// webpack.config.js module: { rules: [ { test: /(\.jsx|\.js)$/, use: { loader: "babel-loader" }, exclude: /node_modules/ }, { test: /\.css$/, use: [ { loader: "style-loader" }, { loader: "css-loader", options: { modules: true, // 指定启用css modules, 这样做有效的避免了全局污染 localIdentName: '[name]__[local]--[hash:base64:5]' // 指定css的类名格式 } } ] } ] }
-
css 预处理器
使用 PostCss 来为CSS代码自动添加适应不同浏览器的CSS前缀 (
-PostCss
是一个CSS的处理平台, 可以帮助你的 css 实现更多的功能, 可以去官方文档了解更多的相关知识)npm install --save-dev postcss-loader autoprefixer
//webpack.config.js module: { rules: [ { test: /(\.jsx|\.js)$/, use: { loader: "babel-loader" }, exclude: /node_modules/ }, { test: /\.css$/, use: [ { loader: "style-loader" }, { loader: "css-loader", options: { modules: true } }, { loader: "postcss-loader" } ] } ] }
// postcss.config.js module.exports = { plugins: [ require('autoprefixer') ] }
-
css 引入
和js文件的引入相同. 请放心的使用,相同的类名也不会造成不同组件之间的污染
import './main.css'; //导入我们的css文件
通常情况下, css 会和 js 打包到同一个文件中, 并不会打包为一个单独的 css 文件, 不过通过配置后 webpack 将把 css 打包为单独的一个文件
关于 css modules 详情可以去官方文档了解更多
插件 (Plugins)
插件(Plugins)是用来拓展Webpack功能的,它们会在整个构建过程中生效,执行相关的任务。
Loaders 和 Plugins 的区别:
-
Loaders 是在打包构建过程中用来处理源文件的(jsx, scss, less ... ), 一次处理一个.
-
Plugins 并不直接操作单个文件, 它直接对整个构建过程起作用.
使用方法:
-
npm 安装你所要使用的插件
-
在 webpack 配置中的 plugins 关键字部分添加该插件的实例
-
Html Webpack Plugin
作用: 依据一个简单的
index.html
模板, 生成一个自动引用你打包后的 JS 文件的新index.html
. 这在生成的js 文件名称不同时非常有用 (比如添加了 hash 值)-
安装插件
npm install --save-dev html-webpack-plugin
-
移除 public 文件夹 ( 该插件会自动生成
index.html
文件 ) -
在 app 目录下创建一份
index.html
文件模板, 同时新建 build 文件夹用来存放最终的输出文件 -
更新 webpack 配置文件
const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: __dirname + "/app/main.js", output: { path: __dirname + "/build", filename: "bundle.js" }, devtool: 'eval-source-map', devServer: { contentBase: "./public", historyApiFallback: true, inline: true//实时刷新 }, module: { rules: [ { test: /(\.jsx|\.js)$/, use: { loader: "babel-loader" }, exclude: /node_modules/ }, { test: /\.css$/, use: [ { loader: "style-loader" }, { loader: "css-loader", options: { modules: true } }, { loader: "postcss-loader" } ] } ] }, plugins: [ new webpack.BannerPlugin('版权所有,翻版必究'), new HtmlWebpackPlugin({ template: __dirname + "/app/index.tmpl.html"//new 一个这个插件的实例,并传入相关的参数 }) ], };
-
产品阶段的构建
在产品阶段,我们可能还需要对打包的文件进行额外的处理, 比如优化,压缩,缓存以及分离css和js.
-
创建一个
webpack.production.config.js
文件用于生产时使用,并添加基本配置// webpack.production.config.js const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: __dirname + "/app/main.js", output: { path: __dirname + "/build", filename: "bundle.js" }, devtool: 'null', //注意修改了这里,这能大大压缩我们的打包代码 devServer: { contentBase: "./public", historyApiFallback: true, inline: true, hot: true }, module: { rules: [{ test: /(\.jsx|\.js)$/, use: { loader: "babel-loader" }, exclude: /node_modules/ }, { test: /\.css$/, use: ExtractTextPlugin.extract({ fallback: "style-loader", use: [{ loader: "css-loader", options: { modules: true } }, { loader: "postcss-loader" }], }) }] }, plugins: [ new webpack.BannerPlugin('版权所有,翻版必究'), new HtmlWebpackPlugin({ template: __dirname + "/app/index.tmpl.html" //new 一个这个插件的实例,并传入相关的参数 }) ], };
注意: 如果是window电脑, build 需要配置为 :
"build": "set NODE_ENV=production && webpack --config ./webpack.production.config.js --progress"
-
优化插件
** ExtractTextPlugin 分离CSS和JS文件**
npm install --save-dev extract-text-webpack-plugin
在配置文件的plugins后引用它们
// webpack.production.config.js ... const ExtractTextPlugin = require('extract-text-webpack-plugin'); ... plugins: [ new webpack.BannerPlugin('版权所有,翻版必究'), new HtmlWebpackPlugin({ template: __dirname + "/app/index.tmpl.html" }), new ExtractTextPlugin("style.css") ] ...
- 最新的webpapck版本已经将
UglifyJsPlugin
的内置插件 (该插件用于压缩js代码) 已经移除,现在直接 运行npm run build
, 生成的js代码将直接被压缩
- 如果运行
npm run build
报错, 很有可能是因为 ExtractTextPlugin 安装的版本问题, 可以尝试安装ExtractTextPlugin的4.0.0-beta.0版本
npm install --save-dev [email protected]
缓存
把一个哈希值添加到打包的文件名中
... output: { path: __dirname + "/build", filename: "bundle-[hash].js" }, ...
clean-webpack-plugin 去除 build 文件中的残余文件
这个插件会清除之前全部打包的js文件
npm install clean-webpack-plugin --save-dev
... const CleanWebpackPlugin = require("clean-webpack-plugin"); ... plugins: [ ... new CleanWebpackPlugin('build/*.*', { root: __dirname, verbose: true, dry: false }) ] ...
- 最新的webpapck版本已经将
至此 入门篇结束
标签:npm,文件,入门,webpack,loader,Webpack,js,css From: https://www.cnblogs.com/icecream-lling/p/17046007.html