Webpack 4x 之路 ( 五 )

在上一篇中我们在html文件中也引用了一张图片,打包完毕后在浏览器控制台报错:

GET file:///D:/myweb/webpack/webpack_study_demo/webpack_new_test/dist/src/asserts/login1.png net::ERR_FILE_NOT_FOUND
// 意思是图片没找到,下面我们就来学习怎么处理HTML中的图片路径问题了
处理HTML中的图片路径问题

webpack处理资源无往不利,但有个问题总是很苦恼,html中直接使用img标签src加载图片的话,因为没有被依赖,图片将不会被打包。这个loader解决这个问题,图片会被打包,而且路径也处理妥当。额外提供html的include子页面功能。

安装

$ cnpm install html-withimg-loader --save

html-withimg-loader

// webpack.config.js
// 然后在生产环境下增加下列代码
config.module.rules.push(
    {
      test: /\.(htm|html)$/i,
      loader: 'html-withimg-loader'
    }
  )
$ npm run build
// 然后你就会发现上面的那个问题得到了解决,图片成功显示,被转为了base64格式写入了

css进阶: less文件的打包与处理

安装less服务

$ cnpm install less less-loader --save-dev
// webpack.config.js
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin')
var webpack = require('webpack')
const isDev = process.env.NODE_ENV === 'development'
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); // 分离css
const uglify = require('uglifyjs-webpack-plugin');// js代码压缩插件

const config = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'js/bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.(jpg|png|svg|gif|jpeg)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit:500000,
              name: 'images/[name]-[hash].[ext]'
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      inject: 'body'
    }),
    new webpack.HotModuleReplacementPlugin()
  ]
}

if (isDev) {
  // 开发环境下
  config.devServer = {
    host: 'localhost',    // 服务器的IP地址,可以使用IP也可以使用localhost
    compress: true,    // 服务端压缩是否开启
    port: 3000, // 端口
    hot: true,
    open: true
  }

  config.module.rules.push(
    {
      test: /\.css$/,
      use: ['style-loader', 'css-loader']
    },
    {                                // 【1】 在开发模式下处理,这里使用的依旧是style-loader
      test: /\.less$/,
      use: ['style-loader', 'css-loader', 'less-loader'] 
    }
  )
} else {
  // 生产模式下
  config.plugins.push(new uglify())
  config.plugins.push(
    new MiniCssExtractPlugin({
      filename: "[name].css",
      chunkFilename: "[id].css"
    })
  )

  config.module.rules.push(
    {
      test: /\.css$/,
      use: [ MiniCssExtractPlugin.loader, 'css-loader']
    },
    {
      test: /\.less$/,                    //【2】 在生产模式下,这里实现了less的分离
      use: [ MiniCssExtractPlugin.loader, 'css-loader','less-loader']
    }
  )
  config.module.rules.push(
    {
      test: /\.(htm|html)$/i,
      loader: 'html-withimg-loader'
    }
  )
}

module.exports = config;
$ npm run build
// 打包成功

css进阶 : SASS打包与处理

安装

$ cnpm install sass --save-dev

这里需要 在项目目录下用npm安装两个包。node-sasssass-loader
因为sass-loader依赖于node-sass,所以需要先安装node-sass

$ cnpm install sass-loader --save-dev
$ cnpm install [email protected] --save-dev
// sass.scss
$nav-color: #FFF;
#nav {
  $width: 100%;
  width: $width;
  height:30px;
  background-color: $nav-color;
}
// 与上面处理less是一样的做法
// webpack.config.js
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin')
var webpack = require('webpack')
const isDev = process.env.NODE_ENV === 'development'
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); // 分离css
const uglify = require('uglifyjs-webpack-plugin');// js代码压缩插件

const config = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'js/bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.(jpg|png|svg|gif|jpeg)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit:500000,
              name: 'images/[name]-[hash].[ext]'
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      inject: 'body'
    }),
    new webpack.HotModuleReplacementPlugin()
  ]
}

if (isDev) {
  // 开发环境下
  config.devServer = {
    host: 'localhost',    // 服务器的IP地址,可以使用IP也可以使用localhost
    compress: true,    // 服务端压缩是否开启
    port: 3000, // 端口
    hot: true,
    open: true
  }

  config.module.rules.push(
    {
      test: /\.css$/,
      use: ['style-loader', 'css-loader']
    },
    {
      test: /\.less$/,
      use: ['style-loader', 'css-loader', 'less-loader'] 
    },
    {
      test: /\.scss$/,             // 【1】 
      use: ['style-loader', 'css-loader', 'sass-loader']
    }
  )
} else {
  // 生产模式下
  config.plugins.push(new uglify())
  config.plugins.push(
    new MiniCssExtractPlugin({
      filename: "[name].css",
      chunkFilename: "[id].css"
    })
  )

  config.module.rules.push(
    {
      test: /\.css$/,
      use: [ MiniCssExtractPlugin.loader, 'css-loader']
    },
    {
      test: /\.less$/,
      use: [ MiniCssExtractPlugin.loader, 'css-loader','less-loader']
    },
    {
      test: /\.scss$/,            // 【2】
      use: [ MiniCssExtractPlugin.loader, 'css-loader','sass-loader']
    }
  )
  config.module.rules.push(
    {
      test: /\.(htm|html)$/i,
      loader: 'html-withimg-loader'
    }
  )
}

module.exports = config;
// $ npm run build
// 没问题

处理css前缀

CSS3已经成了前端的必会技能,但是你一定为那些属性需要加前缀,以满足不同浏览器的兼容,这节课我们就学习一下如何通过postcss-loadercss3属性自动添加前缀。

为了浏览器的兼容性,有时候我们必须加入-webkit,-ms,-o,-moz这些前缀。目的就是让我们写的页面在每个浏览器中都可以顺利运行。

postcss就是一个css的处理器,它有一项非常好的功能就是可以为css添加前缀,这将会使得我们的开发变得非常快速

安装

$  cnpm install --save-dev postcss-loader autoprefixer
// 以及其他插件
$  cnpm install postcss-import --save-dev
$  cnpm install postcss-cssnext --save-dev //一个模块化的缩小器,建立在PostCSS生态系统之上。看到的代码压缩间距就是这个插件的效果
// 样式编写,在每一个样式文件中都加这个
div{
    display: flex;
}
// webpack.config.js
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin')
var webpack = require('webpack')
const isDev = process.env.NODE_ENV === 'development'
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); // 分离css
const uglify = require('uglifyjs-webpack-plugin');// js代码压缩插件

const config = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'js/bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.(jpg|png|svg|gif|jpeg)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 500000,
              name: 'images/[name]-[hash].[ext]'
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      inject: 'body'
    }),
    new webpack.HotModuleReplacementPlugin()
  ]
}

if (isDev) {
  // 开发环境下
  config.devServer = {
    host: 'localhost',    // 服务器的IP地址,可以使用IP也可以使用localhost
    compress: true,    // 服务端压缩是否开启
    port: 3000, // 端口
    hot: true,
    open: true
  }

  config.module.rules.push(
    {
      test: /\.css$/,
      use: [
        'style-loader',
        {
          loader: 'css-loader',
          options: {
            importLoaders: 1
          }
        },
        {
          loader: 'postcss-loader',            // 【1】 加入了postcss-loader
          options: {
            ident: 'postcss',
            plugins: (loader) => [                // 【2】这里使用了一些插件
              require('postcss-import')({ root: loader.resourcePath }),
              require('postcss-cssnext')(),
              require('autoprefixer')(),
              require('cssnano')()
            ]
          }
        }

      ]
    },
    {
      test: /\.less$/,
      use: [
        {
          loader: 'style-loader'
        },
        {
          loader: 'css-loader',
          options: {
            importLoaders: 1
          }
        },
        {
          loader: 'postcss-loader',
          options: {
            ident: 'postcss',
            plugins: (loader) => [
              require('postcss-import')({ root: loader.resourcePath }),
              require('postcss-cssnext')(),
              require('autoprefixer')(),
              require('cssnano')()
            ]
          }
        },
        {
          loader: 'less-loader' // 如果less文件中使用了@import 引入了别的less文件,这里可以不用设置importLoaders
        }
      ]
    },
    {
      test: /\.scss$/,
      use: [
        {
          loader: 'style-loader'
        },
        {
          loader: 'css-loader',
          options: {
            importLoaders: 1
          }
        },
        {
          loader: 'postcss-loader',
          options: {
            ident: 'postcss',
            plugins: (loader) => [
              require('postcss-import')({ root: loader.resourcePath }),
              require('postcss-cssnext')(),
              require('autoprefixer')(),
              require('cssnano')()
            ]
          }
        },
        {
          loader: 'sass-loader'
        }
      ]
    }
  )
} else {
  // 生产模式下
  config.plugins.push(new uglify())
  config.plugins.push(
    new MiniCssExtractPlugin({
      filename: "[name].css",
      chunkFilename: "[id].css"
    })
  )

  config.module.rules.push(
    {
      test: /\.css$/,
      use: [
        MiniCssExtractPlugin.loader,
        'css-loader',
        {
          loader: 'postcss-loader',            //【3】在生产模式下的修改,这里要注意的是位置的放置
          options: {
            ident: 'postcss',
            plugins: (loader) => [
              require('postcss-import')({ root: loader.resourcePath }),
              require('postcss-cssnext')(),
              require('autoprefixer')(),
              require('cssnano')()
            ]
          }
        }
      ]
    },
    {
      test: /\.less$/,
      use: [
        MiniCssExtractPlugin.loader,
        'css-loader',
        {
          loader: 'postcss-loader',
          options: {
            ident: 'postcss',
            plugins: (loader) => [
              require('postcss-import')({ root: loader.resourcePath }),
              require('postcss-cssnext')(),
              require('autoprefixer')(),
              require('cssnano')()
            ]
          }
        },
        'less-loader'
      ]
    },
    {
      test: /\.scss$/,
      use: [
        MiniCssExtractPlugin.loader,
        'css-loader',
        {
          loader: 'postcss-loader',
          options: {
            ident: 'postcss',
            plugins: (loader) => [
              require('postcss-import')({ root: loader.resourcePath }),
              require('postcss-cssnext')(),
              require('autoprefixer')(),
              require('cssnano')()
            ]
          }
        },
        'sass-loader'
      ]
    }
  )
  config.module.rules.push(
    {
      test: /\.(htm|html)$/i,
      loader: 'html-withimg-loader'
    }
  )
}

module.exports = config;

// postcss使用
// 将`postcss-loader`添加到 `webpack.config.js` 中,您可以单独的使用它,也可以是与 `css-loader` 一起使用。在css-loader和style-loader之后使用它,但是在其他预处理器加载器(如less-loader)之前使用它
$ npm run dev
// 执行后发现前缀添加完毕,并且代码做了一定的压缩
使用babel

babel可以干什么呢?

  1. 可以让你使用使用下一代javascript代码(ES6\ES7),即使这些标准目前还没有被所有浏览器所支持
  2. 使用基于javascript进行了扩展的语言,比如Reactjsx;

安装

$ cnpm install babel-core babel-loader babel-preset-env --save-dev
// 再目录下建立.babelrc文件
{
    "presets":["env"]
}
// webpack.config.js
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin')
var webpack = require('webpack')
const isDev = process.env.NODE_ENV === 'development'
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); // 分离css
const uglify = require('uglifyjs-webpack-plugin');// js代码压缩插件
const glob = require('glob');
const PurifyCSSPlugin = require("purifycss-webpack");


const config = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'js/bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.(jpg|png|svg|gif|jpeg)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 500000,
              name: 'images/[name]-[hash].[ext]'
            }
          }
        ]
      },
      {
        test: /\.js$/,            // 【1】 更改这里
        use: [
          'babel-loader'
        ],
        exclude: /(node_modules|bower_components)/  // 优化处理加快速度
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      inject: 'body'
    }),
    new webpack.HotModuleReplacementPlugin(),
    new PurifyCSSPlugin({
      // Give paths to parse for rules. These should be absolute!
      paths: glob.sync(path.join(__dirname, 'src/*.html')),
    })
  ]
}

if (isDev) {
  // 开发环境下
  config.devServer = {
    host: 'localhost',    // 服务器的IP地址,可以使用IP也可以使用localhost
    compress: true,    // 服务端压缩是否开启
    port: 3000, // 端口
    hot: true,
    open: true
  }

  config.module.rules.push(
    {
      test: /\.css$/,
      use: [
        'style-loader',
        {
          loader: 'css-loader',
          options: {
            importLoaders: 1
          }
        },
        {
          loader: 'postcss-loader',
          options: {
            ident: 'postcss',
            plugins: (loader) => [
              require('postcss-import')({ root: loader.resourcePath }),
              require('postcss-cssnext')(),
              require('autoprefixer')(),
              require('cssnano')()
            ]
          }
        }

      ]
    },
    {
      test: /\.less$/,
      use: [
        {
          loader: 'style-loader'
        },
        {
          loader: 'css-loader',
          options: {
            importLoaders: 1
          }
        },
        {
          loader: 'postcss-loader',
          options: {
            ident: 'postcss',
            plugins: (loader) => [
              require('postcss-import')({ root: loader.resourcePath }),
              require('postcss-cssnext')(),
              require('autoprefixer')(),
              require('cssnano')()
            ]
          }
        },
        {
          loader: 'less-loader' // 如果less文件中使用了@import 引入了别的less文件,这里可以不用设置importLoaders
        }
      ]
    },
    {
      test: /\.scss$/,
      use: [
        {
          loader: 'style-loader'
        },
        {
          loader: 'css-loader',
          options: {
            importLoaders: 1
          }
        },
        {
          loader: 'postcss-loader',
          options: {
            ident: 'postcss',
            plugins: (loader) => [
              require('postcss-import')({ root: loader.resourcePath }),
              require('postcss-cssnext')(),
              require('autoprefixer')(),
              require('cssnano')()
            ]
          }
        },
        {
          loader: 'sass-loader'
        }
      ]
    }
  )
} else {
  // 生产模式下
  config.plugins.push(new uglify())
  config.plugins.push(
    new MiniCssExtractPlugin({
      filename: "[name].css",
      chunkFilename: "[id].css"
    })
  )

  config.module.rules.push(
    {
      test: /\.css$/,
      use: [
        MiniCssExtractPlugin.loader,
        'css-loader',
        {
          loader: 'postcss-loader',
          options: {
            ident: 'postcss',
            plugins: (loader) => [
              require('postcss-import')({ root: loader.resourcePath }),
              require('postcss-cssnext')(),
              require('autoprefixer')(),
              require('cssnano')()
            ]
          }
        }
      ]
    },
    {
      test: /\.less$/,
      use: [
        MiniCssExtractPlugin.loader,
        'css-loader',
        {
          loader: 'postcss-loader',
          options: {
            ident: 'postcss',
            plugins: (loader) => [
              require('postcss-import')({ root: loader.resourcePath }),
              require('postcss-cssnext')(),
              require('autoprefixer')(),
              require('cssnano')()
            ]
          }
        },
        'less-loader'
      ]
    },
    {
      test: /\.scss$/,
      use: [
        MiniCssExtractPlugin.loader,
        'css-loader',
        {
          loader: 'postcss-loader',
          options: {
            ident: 'postcss',
            plugins: (loader) => [
              require('postcss-import')({ root: loader.resourcePath }),
              require('postcss-cssnext')(),
              require('autoprefixer')(),
              require('cssnano')()
            ]
          }
        },
        'sass-loader'
      ]
    }
  )
  config.module.rules.push(
    {
      test: /\.(htm|html)$/i,
      loader: 'html-withimg-loader'
    }
  )
}

module.exports = config;

测试

// index.js
import './styles/reset.css';
import './styles/index.css';
import './styles/base.less';
import './styles/sass.scss';

{
    let title = 'hello';
    document.getElementById('title').innerHTML = title;
}

// 测试发现没问题

感谢您的支持!!

相关推荐