ps:每一个案例都是基于前一个案例改造的javascript
webpack入门(1) 戳这里css
案例源码戳这里html
自动加载模块java
new webpack.ProvidePlugin()node
上面的案例太复杂,下面再新建一个简单的项目来说解react
新建一个项目,以下jquery
[webpack] |-- src |-- index.html |-- index.less |-- index.js |-- package.json |-- webpack.config.js
webpack/package.jsonwebpack
{ "name": "webpack", "version": "1.0.0", "description": "", "scripts": { "start": "webpack-dev-server --content-base build --inline --hot", "build": "webpack -p", "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "devDependencies": { "babel-core": "^6.26.0", "babel-loader": "^7.1.2", "babel-preset-es2015": "^6.24.1", "css-loader": "^0.28.7", "extract-text-webpack-plugin": "^3.0.2", "file-loader": "^1.1.5", "html-webpack-plugin": "^2.30.1", "jquery": "^3.2.1", "less": "^2.7.3", "less-loader": "^4.0.5", "style-loader": "^0.19.0", "url-loader": "^0.6.2", "webpack": "^3.10.0", "webpack-dev-server": "^2.9.5" } }
webpack/webpack.config.jsgit
var webpack = require('webpack'); var HtmlWebpackPlugin = require('html-webpack-plugin'); var ExtractTextPlugin = require("extract-text-webpack-plugin"); module.exports = { entry: { // 入口文件地址 index: './src/index.js', jquery: [ "jquery" ] }, output: { // 出口 path: __dirname + "/build", // 打包后的文件存放路径 filename: '[name].js' // 文件名,name即为entry的key }, module: { loaders: [ { test: /\.js$/, // js-loader loader: 'babel-loader?presets=es2015' }, { test: /\.css$/, // css-loader loader: ExtractTextPlugin.extract('css-loader') }, { test: /\.less/, // less-loader loaders: ExtractTextPlugin.extract('css-loader!less-loader') }, { test: /\.(png|jpg)$/, // img-loader loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]' } ], }, plugins: [ new HtmlWebpackPlugin({ filename: 'index.html', // 生成的的html文件名 template: './src/index.html', // 被打包的html路径 chunks: ['index', 'jquery'] // 须要引入的js,对应entry的key }), new ExtractTextPlugin({ // 单独打包css filename: '[name].css' }), new webpack.optimize.CommonsChunkPlugin({ name: 'jquery' // 对应entry的key }), new webpack.ProvidePlugin({ // 全局引入jquery $: 'jquery' }) ] }
webpack/src/index.htmlgithub
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>webpackDemo</title> </head> <body> </body> </html>
webpack/src/index.less
body { background: lightpink; }
webpack/src/index.js
import './index.less'; $('body').prepend('hi');
在webpack.config.js里设置了全局引入jquery,这里就不须要
import $ from 'jquery'
能够直接用 $
$ npm run start , 打开 http://localhost:8080/index.html , 效果以下
点击这里下载 案例17 使用的iconfont文件,如下简称“案例17压缩包”
新增文件 iconfont.less 和 iconfont.ttf(案例17压缩包里的iconfont.ttf),将index.less移动至css文件夹下,以下
[webpack] |-- src |-- images |-- iconfont.ttf |-- css |-- iconfont.less |-- index.less |-- index.html |-- index.js |-- package.json |-- webpack.config.js
webpack/src/css/iconfont.less
@font-face { font-family: "iconfont"; src: url('../images/iconfont.ttf') format('truetype'); } .iconfont { font-family: "iconfont" !important; font-size: 16px; font-style: normal; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .icon-love:before { content: "\e612"; }
webpack/src/css/index.less
@import './iconfont.less'; body { background: lightpink; .iconfont { font-size: 50px; } }
webpack/src/index.js
import './css/index.less'; $('body').prepend('<i class="iconfont icon-love"></i>');
webpack/webpack.config.js
var webpack = require('webpack'); var HtmlWebpackPlugin = require('html-webpack-plugin'); var ExtractTextPlugin = require("extract-text-webpack-plugin"); module.exports = { entry: { // 入口文件地址 index: './src/index.js', jquery: [ "jquery" ] }, output: { // 出口 path: __dirname + "/build", // 打包后的文件存放路径 filename: '[name].js' // 文件名,name即为entry的key }, module: { loaders: [ { test: /\.js$/, // js-loader loader: 'babel-loader?presets=es2015' }, { test: /\.css$/, // css-loader loader: ExtractTextPlugin.extract('css-loader') }, { test: /\.less/, // less-loader loaders: ExtractTextPlugin.extract('css-loader!less-loader') }, { test: /\.(png|jpg|ttf)$/, // img-loader loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]' } ], }, plugins: [ new HtmlWebpackPlugin({ filename: 'index.html', // 生成的的html文件名 template: './src/index.html', // 被打包的html路径 chunks: ['index', 'jquery'] // 须要引入的js,对应entry的key }), new ExtractTextPlugin({ // 单独打包css filename: '[name].css' }), new webpack.optimize.CommonsChunkPlugin({ name: 'jquery' // 对应entry的key }), new webpack.ProvidePlugin({ // 全局引入jquery $: 'jquery' }) ] }
本案例只引入了ttf,其余能够相似添加
{ test: /\.(png|jpg|ttf|svg|eot|woff)$/, // img-loader loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]' }
$ npm run start , 打开 http://localhost:8080/index.html ,效果以下
$ npm run build , iconfont.ttf文件小会转为base64直接打包到index.css里,若是文件比较大,则会单独打包到webpack/build/images/iconfont.ttf
externals 配置选项提供了「从输出的 bundle 中排除依赖」的方法。
好比 jquery 但愿经过 cdn 的方式引入,代码里依旧用 import 的方式来使用,可是又不但愿被打包。
webpack/src/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>webpackDemo</title> </head> <body> <script src="https://code.jquery.com/jquery-3.1.0.js"></script> </body> </html>
webpack/src/index.js
import $ from 'jquery'; import './css/index.less'; $('body').prepend('<i class="iconfont icon-love"></i>');
webpack/webpack.config.js
var webpack = require('webpack'); var HtmlWebpackPlugin = require('html-webpack-plugin'); var ExtractTextPlugin = require("extract-text-webpack-plugin"); module.exports = { entry: { // 入口文件地址 index: './src/index.js' }, output: { // 出口 path: __dirname + "/build", // 打包后的文件存放路径 filename: '[name].js' // 文件名,name即为entry的key }, externals: { jquery: 'jQuery' // jquery不被webpack编译到文件中 }, module: { loaders: [ { test: /\.js$/, // js-loader loader: 'babel-loader?presets=es2015' }, { test: /\.css$/, // css-loader loader: ExtractTextPlugin.extract('css-loader') }, { test: /\.less/, // less-loader loaders: ExtractTextPlugin.extract('css-loader!less-loader') }, { test: /\.(png|jpg|ttf)$/, // img-loader loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]' } ], }, plugins: [ new HtmlWebpackPlugin({ filename: 'index.html', // 生成的的html文件名 template: './src/index.html', // 被打包的html路径 chunks: ['index'] // 须要引入的js,对应entry的key }), new ExtractTextPlugin({ // 单独打包css filename: '[name].css' }) ] }
运行 $ npm run build , 生成文件目录以下
[webpack] |-- build |-- index.css |-- index.html |-- index.js
安装依赖
$ npm i babel-preset-react react react-dom --save-dev
webpack/src/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>webpackDemo</title> </head> <body> <div id="root"></div> </body> </html>
webpack/src/index.js
import React from 'react'; import ReactDOM from 'react-dom'; import './css/index.less'; class Demo extends React.Component { render() { return ( <i className="iconfont icon-love" /> ); } } ReactDOM.render( <Demo />, document.getElementById('root') );
webpack/webpack.config.js
var webpack = require('webpack'); var HtmlWebpackPlugin = require('html-webpack-plugin'); var ExtractTextPlugin = require("extract-text-webpack-plugin"); module.exports = { entry: { // 入口文件地址 index: './src/index.js' }, output: { // 出口 path: __dirname + "/build", // 打包后的文件存放路径 filename: '[name].js' // 文件名,name即为entry的key }, module: { loaders: [ { test: /\.(js|jsx)$/, // js-loader loader: 'babel-loader?presets[]=es2015&presets[]=react' }, { test: /\.css$/, // css-loader loader: ExtractTextPlugin.extract('css-loader') }, { test: /\.less/, // less-loader loaders: ExtractTextPlugin.extract('css-loader!less-loader') }, { test: /\.(png|jpg|ttf)$/, // img-loader loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]' } ], }, plugins: [ new HtmlWebpackPlugin({ filename: 'index.html', // 生成的的html文件名 template: './src/index.html', // 被打包的html路径 chunks: ['index'] // 须要引入的js,对应entry的key }), new ExtractTextPlugin({ // 单独打包css filename: '[name].css' }) ] }
须要babel-preset-react插件来编译React
运行 $ npm run start , 打开 http://localhost:8080/ ,能看到效果
运行 $ npm run build ,打包文件目录以下:
[webpack] |-- build |-- index.css |-- index.html |-- index.js
react被打包到webpack/build/index.js里去了
webpack/src/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>webpackDemo</title> </head> <body> <div id="root"></div> <script src="https://cdn.bootcss.com/react/15.4.2/react.min.js"></script> <script src="https://cdn.bootcss.com/react/15.4.2/react-dom.min.js"></script> </body> </html>
webpack/webpack.config.js
var webpack = require('webpack'); var HtmlWebpackPlugin = require('html-webpack-plugin'); var ExtractTextPlugin = require("extract-text-webpack-plugin"); module.exports = { entry: { // 入口文件地址 index: './src/index.js' }, output: { // 出口 path: __dirname + "/build", // 打包后的文件存放路径 filename: '[name].js' // 文件名,name即为entry的key }, externals: { 'react': 'React', 'react-dom': 'ReactDOM' }, module: { loaders: [ { test: /\.(js|jsx)$/, // js-loader loader: 'babel-loader?presets[]=es2015&presets[]=react' }, { test: /\.css$/, // css-loader loader: ExtractTextPlugin.extract('css-loader') }, { test: /\.less/, // less-loader loaders: ExtractTextPlugin.extract('css-loader!less-loader') }, { test: /\.(png|jpg|ttf)$/, // img-loader loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]' } ], }, plugins: [ new HtmlWebpackPlugin({ filename: 'index.html', // 生成的的html文件名 template: './src/index.html', // 被打包的html路径 chunks: ['index'] // 须要引入的js,对应entry的key }), new ExtractTextPlugin({ // 单独打包css filename: '[name].css' }) ] }
这样 react 就不会被打包入 webpack/build/index.js
新建一个项目以下
[webpack] |-- package.json |-- webpack.config.js |-- src |-- index.html |-- index.js |-- images |-- SpongeBob.jpg |-- css |-- index.less
本案例用到的图片 SpongeBob.jpg 戳这里
webpack/package.json
{ "name": "webpack", "version": "1.0.0", "description": "", "scripts": { "start": "webpack-dev-server", "build": "webpack -p" }, "author": "", "license": "ISC", "devDependencies": { "babel-core": "^6.26.0", "babel-loader": "^7.1.2", "babel-preset-es2015": "^6.24.1", "babel-preset-react": "^6.24.1", "css-loader": "^0.28.7", "extract-text-webpack-plugin": "^3.0.2", "file-loader": "^1.1.5", "html-webpack-plugin": "^2.30.1", "jquery": "^3.2.1", "less": "^2.7.3", "less-loader": "^4.0.5", "style-loader": "^0.19.0", "url-loader": "^0.6.2", "webpack": "^3.10.0", "webpack-dev-server": "^2.9.5" } }
webpack/webpack.config.js
var webpack = require('webpack'); var HtmlWebpackPlugin = require('html-webpack-plugin'); var ExtractTextPlugin = require("extract-text-webpack-plugin"); module.exports = { entry: { // 入口文件地址 index: './src/index.js' }, output: { // 出口 path: __dirname + "/build", // 打包后的文件存放路径 filename: '[name].js' // 文件名,name即为entry的key }, externals: { 'jquery': 'jQuery', // 不打包jquery }, module: { loaders: [ { test: /\.(js|jsx)$/, // js-loader loader: 'babel-loader?presets[]=es2015&presets[]=react' }, { test: /\.less/, // less-loader loaders: ExtractTextPlugin.extract('css-loader!less-loader') }, { test: /\.(png|jpg|ttf)$/, // img-loader loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]' } ], }, devServer: { contentBase: './build', inline: true, hot: true }, plugins: [ new webpack.HotModuleReplacementPlugin(), // 启用热替换模块 new HtmlWebpackPlugin({ filename: 'index.html', // 生成的的html文件名 template: './src/index.html', // 被打包的html路径 chunks: ['index'] // 须要引入的js,对应entry的key }), new ExtractTextPlugin({ // 单独打包css filename: '[name].css' }) ] }
webpack/src/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>webpackDemo</title> </head> <body> <script src="https://code.jquery.com/jquery-3.1.0.js"></script> </body> </html>
webpack/src/css/index.less
body { background: url(../images/SpongeBob.jpg) no-repeat; color: blue; }
webpack/src/index.js
import './css/index.less'; $('body').prepend('hi')
package.json 对比
// 案例16 "scripts": { "start": "webpack-dev-server --content-base build --inline --hot", } // 案例21 "scripts": { "start": "webpack-dev-server", }
案例21 中 webpack-dev-server 后的参数,改成在 webapck.config.js 中设置
{ devServer: { contentBase: './build', inline: true, hot: true }, plugins: [ new webpack.HotModuleReplacementPlugin() ] }
$ npm run start , 打开 http://localhost:8080/ , 效果以下
{ devServer: { before: (app) =>{ app.get('/init.json', function(req, res) { res.json({ title: 'webpack' }); }); } } }
webpack/webpack.config.js
var webpack = require('webpack'); var HtmlWebpackPlugin = require('html-webpack-plugin'); var ExtractTextPlugin = require("extract-text-webpack-plugin"); module.exports = { entry: { // 入口文件地址 index: './src/index.js' }, output: { // 出口 path: __dirname + "/build", // 打包后的文件存放路径 filename: '[name].js' // 文件名,name即为entry的key }, externals: { 'jquery': 'jQuery', // 不打包jquery }, module: { loaders: [ { test: /\.(js|jsx)$/, // js-loader loader: 'babel-loader?presets[]=es2015&presets[]=react' }, { test: /\.less/, // less-loader loaders: ExtractTextPlugin.extract('css-loader!less-loader') }, { test: /\.(png|jpg|ttf)$/, // img-loader loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]' } ], }, devServer: { contentBase: './build', inline: true, hot: true, before: (app) =>{ app.get('/init.json', function(req, res) { res.json({ title: 'webpack' }); }); } }, plugins: [ new webpack.HotModuleReplacementPlugin(), // 启用热替换模块 new HtmlWebpackPlugin({ filename: 'index.html', // 生成的的html文件名 template: './src/index.html', // 被打包的html路径 chunks: ['index'] // 须要引入的js,对应entry的key }), new ExtractTextPlugin({ // 单独打包css filename: '[name].css' }) ] }
webpack/src/index.js
import './css/index.less'; $.ajax({ url: '/init.json', data: {}, type: 'GET', success: (d = {}) => { $('body').prepend(d.title); }, error: () => { $('body').prepend('ajax error'); } });
$ npm run start , 打开 http://localhost:8080/index.html , 效果以下
若是是 post 请求,webpack.config.js 以下
{ devServer: { before: (app) =>{ app.post('/init.json', function(req, res) { res.json({ title: 'webpack' }); }); } } }
固然,也能够不在 res.json() 中直接写 mock 数据,能够在外面命名变量,或者从其余文件引入
var mock_init = require('xxxxx'); var mock_user = { title: 'webpack' }; module.exports = { devServer: { before: (app) =>{ app.post('/init.json', function(req, res) { res.json(mock_init); }); app.post('/user.json', function(req, res) { res.json(mock_user); }); } } }
DefinePlugin 能够把命令行的环境变量带到浏览器端。
new webpack.DefinePlugin()
环境变量在不少状况都会使用,这里举一个例子,好比咱们本地 mock 数据时,请求都是 "localhost:8080" 开头的,可是到线上了则是 "http://a.com" 和 "http://b.com" , 这个时候就可使用 DefinePlugin 来解决
webpack/package.json
{ "name": "webpack", "version": "1.0.0", "description": "", "scripts": { "start": "NODE_ENV=mock webpack-dev-server", "prod": "NODE_ENV=prod webpack-dev-server", "build-start": "NODE_ENV=mock webpack -p", "build-prod": "NODE_ENV=prod webpack -p" }, "author": "", "license": "ISC", "devDependencies": { "babel-core": "^6.26.0", "babel-loader": "^7.1.2", "babel-preset-es2015": "^6.24.1", "babel-preset-react": "^6.24.1", "css-loader": "^0.28.7", "extract-text-webpack-plugin": "^3.0.2", "file-loader": "^1.1.5", "html-webpack-plugin": "^2.30.1", "jquery": "^3.2.1", "less": "^2.7.3", "less-loader": "^4.0.5", "style-loader": "^0.19.0", "url-loader": "^0.6.2", "webpack": "^3.10.0", "webpack-dev-server": "^2.9.5" } }
"NODE_ENV=xxx" , 能够定义不一样环境的 NODE_ENV
start 和 build-start , 是咱们本地开发时使用 ; prod 和 build-prod , 是线上环境使用
webpack/webpack.config.js
var webpack = require('webpack'); var HtmlWebpackPlugin = require('html-webpack-plugin'); var ExtractTextPlugin = require("extract-text-webpack-plugin"); console.log('----------- NODE_ENV ----------- : ', process.env.NODE_ENV) module.exports = { entry: { // 入口文件地址 index: './src/index.js' }, output: { // 出口 path: __dirname + "/build", // 打包后的文件存放路径 filename: '[name].js' // 文件名,name即为entry的key }, externals: { 'jquery': 'jQuery', // 不打包jquery }, module: { loaders: [ { test: /\.(js|jsx)$/, // js-loader loader: 'babel-loader?presets[]=es2015&presets[]=react' }, { test: /\.less/, // less-loader loaders: ExtractTextPlugin.extract('css-loader!less-loader') }, { test: /\.(png|jpg|ttf)$/, // img-loader loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]' } ], }, devServer: { contentBase: './build', inline: true, hot: true, before: (app) =>{ app.get('/init.json', function(req, res) { res.json({ title: 'webpack' }); }); } }, plugins: [ new webpack.HotModuleReplacementPlugin(), // 启用热替换模块 new HtmlWebpackPlugin({ filename: 'index.html', // 生成的的html文件名 template: './src/index.html', // 被打包的html路径 chunks: ['index'] // 须要引入的js,对应entry的key }), new ExtractTextPlugin({ // 单独打包css filename: '[name].css' }) ] }
经过 process.env.NODE_ENV 变量拿到值
$ npm run start , 效果以下
$ npm run prod , 效果以下
webpack/webpack.config.js
var webpack = require('webpack'); var HtmlWebpackPlugin = require('html-webpack-plugin'); var ExtractTextPlugin = require("extract-text-webpack-plugin"); const checkHost = { "mock": { "A_HOST": "http://localhost:8080", "B_HOST": "http://localhost:8080", }, "prod": { "A_HOST": "http://a.com", "B_HOST": "http://b.com", } } var checkHostKey = checkHost[process.env.NODE_ENV] ? process.env.NODE_ENV : 'mock'; var checkHostContent = checkHost[checkHostKey]; for (i in checkHostContent) { checkHostContent[i] = JSON.stringify(checkHostContent[i]); } module.exports = { entry: { // 入口文件地址 index: './src/index.js' }, output: { // 出口 path: __dirname + "/build", // 打包后的文件存放路径 filename: '[name].js' // 文件名,name即为entry的key }, externals: { 'jquery': 'jQuery', // 不打包jquery }, module: { loaders: [ { test: /\.(js|jsx)$/, // js-loader loader: 'babel-loader?presets[]=es2015&presets[]=react' }, { test: /\.less/, // less-loader loaders: ExtractTextPlugin.extract('css-loader!less-loader') }, { test: /\.(png|jpg|ttf)$/, // img-loader loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]' } ], }, devServer: { contentBase: './build', inline: true, hot: true, before: (app) =>{ app.get('/init.json', function(req, res) { res.json({ title: 'webpack' }); }); } }, plugins: [ new webpack.DefinePlugin(checkHostContent), new webpack.HotModuleReplacementPlugin(), // 启用热替换模块 new HtmlWebpackPlugin({ filename: 'index.html', // 生成的的html文件名 template: './src/index.html', // 被打包的html路径 chunks: ['index'] // 须要引入的js,对应entry的key }), new ExtractTextPlugin({ // 单独打包css filename: '[name].css' }) ] }
分析以下
const checkHost = { "mock": { // 本地 mock 数据使用 "A_HOST": "http://localhost:8080", "B_HOST": "http://localhost:8080", }, "prod": { // 线上环境使用 "A_HOST": "http://a.com", "B_HOST": "http://b.com", } } // 检查 checkHost[process.env.NODE_ENV] 是否存在,不存在时,将rocess.env.NODE_ENV 设置为 mock var checkHostKey = checkHost[process.env.NODE_ENV] ? process.env.NODE_ENV : 'mock'; // checkHostContent 至关因而 checkHost.mock 或 checkHost.prod var checkHostContent = checkHost[checkHostKey]; // 若是 DefinePlugin 键值是一个字符串,它会被看成一个代码片断来使用,须要 JSON.stringify() 处理 for (i in checkHostContent) { checkHostContent[i] = JSON.stringify(checkHostContent[i]); } // 将处理好的 checkHostContent 放入 module.exports = { plugins: [new webpack.DefinePlugin(checkHostContent)] }
这一部分代码,将咱们要用到的 A_HOST 和 B_HOST 都处理好,再放入new webpack.DefinePlugin(),拿 prod 举例,至关于处理成
module.exports = { plugins: [new webpack.DefinePlugin({ A_HOST: JSON.stringify("http://a.com"), B_HOST: JSON.stringify("http://b.com"), })] }
webpack/src/index.js
import './css/index.less'; console.log(A_HOST, B_HOST) $.ajax({ url: `${A_HOST}/init.json`, data: {}, type: 'GET', success: (d = {}) => { $('body').prepend(d.title); }, error: () => { $('body').prepend('ajax error'); } });
$ npm run start , 效果以下
$ npm run prod , 效果以下
固然,也能够直接写两个 webpack.config.js 文件,这里就贴一下代码,不具体写案例了
// webpack.start.config.js module.exports = { plugins: [new webpack.DefinePlugin({ A_HOST: JSON.stringify("http://localhost:8080"), B_HOST: JSON.stringify("http://localhost:8080"), })] } // webpack.prod.config.js module.exports = { plugins: [new webpack.DefinePlugin({ A_HOST: JSON.stringify("http://a.com"), B_HOST: JSON.stringify("http://b.com"), })] } // package.json { "scripts": { "start": "webpack-dev-server --config webpack.start.config.js", "prod": "webpack-dev-server --config webpack.prod.config.js", "build-start": "webpack -p --config webpack.start.config.js", "build-prod": "webpack -p --config webpack.prod.config.js" } }
新增 webpack/server.js , 目录以下
[webpack] |-- server.js |-- package.json |-- webpack.config.js |-- src |-- index.html |-- index.js |-- images |-- SpongeBob.jpg |-- css |-- index.less
webpack/webpack.config.js
var webpack = require('webpack'); var HtmlWebpackPlugin = require('html-webpack-plugin'); var ExtractTextPlugin = require("extract-text-webpack-plugin"); const checkHost = { "mock": { // 本地 mock 数据使用 "A_HOST": "http://localhost:8080", "B_HOST": "http://localhost:8080", }, "prod": { // 线上环境使用 "A_HOST": "http://a.com", "B_HOST": "http://b.com", } } // 检查 process.env.NODE_ENV 是否和 checkHost 里的对应 var checkHostKey = checkHost[process.env.NODE_ENV] ? process.env.NODE_ENV : 'mock'; // checkHostContent 至关因而 checkHost.mock 或 checkHost.prod var checkHostContent = checkHost[checkHostKey]; // 若是 DefinePlugin 键值是是一个字符串,它会被看成一个代码片断来使用,须要 JSON.stringify() 处理 for (i in checkHostContent) { checkHostContent[i] = JSON.stringify(checkHostContent[i]); } module.exports = { entry: { // 入口文件地址 index: ['./src/index.js'] }, output: { // 出口 path: __dirname + "/build", // 打包后的文件存放路径 filename: '[name].js' // 文件名,name即为entry的key }, externals: { 'jquery': 'jQuery', // 不打包jquery }, module: { loaders: [ { test: /\.(js|jsx)$/, // js-loader loader: 'babel-loader?presets[]=es2015&presets[]=react' }, { test: /\.less/, // less-loader loaders: ExtractTextPlugin.extract('css-loader!less-loader') }, { test: /\.(png|jpg|ttf)$/, // img-loader loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]' } ], }, plugins: [ new webpack.DefinePlugin(checkHostContent), // 将处理好的 checkHostContent 放入 new webpack.HotModuleReplacementPlugin(), // 启用热替换模块 new HtmlWebpackPlugin({ filename: 'index.html', // 生成的的html文件名 template: './src/index.html', // 被打包的html路径 chunks: ['index'] // 须要引入的js,对应entry的key }), new ExtractTextPlugin({ // 单独打包css filename: '[name].css' }) ] }
将 devServer 删除 , entry.index 改成 array 写法
webpack/server.js
// 引入 webpack 和 webpack-dev-server var webpack = require('webpack'); var WebpackDevServer = require('webpack-dev-server'); // 引入 webpack 的配置 var config = require('./webpack.config.js'); // 添加 webpack-dev-server 的客户端入口文件到 webpack 的配置中 // 经过 unshift 方法,将 webpack-dev-server/client?http://«path»:«port»/ 插入到 webpack-dev-server 配置的 entry.index 中 config.entry.index.unshift("webpack-dev-server/client?http://localhost:8080/"); // compiler = webpack({ webpack 的配置 }) var compiler = webpack(config); // server = new WebpackDevServer(compiler, { devServer 的配置 }) var server = new WebpackDevServer(compiler, { contentBase: './build', inline: true, hot: true, before: (app) =>{ app.get('/init.json', function(req, res) { res.json({ title: 'webpack' }); }); } }); server.listen(8080, "localhost", function() {});
webpack-dev-server 的配置里没有 inline : true 这个配置项, 由于 webpack-dev-server 没法访问 webpack 的配置。 所以,用户必须添加 webpack-dev-server 的客户端入口文件到 webpack 的配置中,有如下几种方式(上面案例只写了一种,其余你们能够自行尝试)
// server.js config.entry.app.unshift("webpack-dev-server/client?http://localhost:8080/"); // webpack.config.js { entry: { index: [ 'webpack-dev-server/client?http://localhost:8080/', './src/index.js' ] } } // index.html <script src="http://localhost:8080/webpack-dev-server.js"></script>
webpack/package.json
{ "name": "webpack", "version": "1.0.0", "description": "", "scripts": { "start": "NODE_ENV=mock node server.js", "prod": "NODE_ENV=prod node server.js", "build-start": "NODE_ENV=mock webpack -p", "build-prod": "NODE_ENV=prod webpack -p" }, "author": "", "license": "ISC", "devDependencies": { "babel-core": "^6.26.0", "babel-loader": "^7.1.2", "babel-preset-es2015": "^6.24.1", "babel-preset-react": "^6.24.1", "css-loader": "^0.28.7", "extract-text-webpack-plugin": "^3.0.2", "file-loader": "^1.1.5", "html-webpack-plugin": "^2.30.1", "jquery": "^3.2.1", "less": "^2.7.3", "less-loader": "^4.0.5", "style-loader": "^0.19.0", "url-loader": "^0.6.2", "webpack": "^3.10.0", "webpack-dev-server": "^2.9.5" } }
修改了 scripts.start 和 scripts.prod ,$ npm run start 和 $ npm run prod ,效果和 案例23 同样
下面介绍一下 loaders 的其余写法
webpack/server.js
var webpack = require('webpack'); var HtmlWebpackPlugin = require('html-webpack-plugin'); var ExtractTextPlugin = require("extract-text-webpack-plugin"); const checkHost = { "mock": { // 本地 mock 数据使用 "A_HOST": "http://localhost:8080", "B_HOST": "http://localhost:8080", }, "prod": { // 线上环境使用 "A_HOST": "http://a.com", "B_HOST": "http://b.com", } } // 检查 process.env.NODE_ENV 是否和 checkHost 里的对应 var checkHostKey = checkHost[process.env.NODE_ENV] ? process.env.NODE_ENV : 'mock'; // checkHostContent 至关因而 checkHost.mock 或 checkHost.prod var checkHostContent = checkHost[checkHostKey]; // 若是 DefinePlugin 键值是是一个字符串,它会被看成一个代码片断来使用,须要 JSON.stringify() 处理 for (i in checkHostContent) { checkHostContent[i] = JSON.stringify(checkHostContent[i]); } module.exports = { entry: { // 入口文件地址 index: ['./src/index.js'] }, output: { // 出口 path: __dirname + "/build", // 打包后的文件存放路径 filename: '[name].js' // 文件名,name即为entry的key }, externals: { 'jquery': 'jQuery', // 不打包jquery }, module: { rules: [ // loaders { test: /\.(js|jsx)$/, use: { loader: 'babel-loader', options: { presets: ['es2015', 'react'] } } }, { test: /\.less$/, use: ExtractTextPlugin.extract({ use: [{ loader: "css-loader" }, { loader: "less-loader" }] }) }, { test: /\.(png|jpg|ttf)$/, use: [ { loader: 'url-loader', options: { limit: 8192, name: 'images/[hash:8].[name].[ext]' } } ] } ] }, plugins: [ new webpack.DefinePlugin(checkHostContent), // 将处理好的 checkHostContent 放入 new webpack.HotModuleReplacementPlugin(), // 启用热替换模块 new HtmlWebpackPlugin({ filename: 'index.html', // 生成的的html文件名 template: './src/index.html', // 被打包的html路径 chunks: ['index'] // 须要引入的js,对应entry的key }), new ExtractTextPlugin({ // 单独打包css filename: '[name].css' }) ] }
对比分析以下
{ module: { // module.loaders 改成 module.rules rules: [ // { // test: /\.(js|jsx)$/, // js-loader // loader: 'babel-loader?presets[]=es2015&presets[]=react' // } { test: /\.(js|jsx)$/, use: { loader: 'babel-loader', options: { // ? 后的参数能够写在这里 presets: ['es2015', 'react'] } } }, // { // test: /\.less/, // less-loader // loaders: ExtractTextPlugin.extract('css-loader!less-loader') // } { test: /\.less$/, use: ExtractTextPlugin.extract({ use: [{ loader: "css-loader" }, { loader: "less-loader" }] }) }, // { // test: /\.(png|jpg|ttf)$/, // img-loader // loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]' // } { test: /\.(png|jpg|ttf)$/, use: [ { loader: 'url-loader', options: { limit: 8192, name: 'images/[hash:8].[name].[ext]' } } ] } ] } }