├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── jest.config.js ├── package.json ├── renovate.json ├── src └── module.ts ├── test ├── dev.test.ts ├── fixture │ ├── assets │ │ └── example.png │ ├── nuxt.config.js │ └── pages │ │ └── index.vue ├── prod.test.ts └── warn.test.ts ├── tsconfig.json └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_size = 2 6 | indent_style = space 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # Common 2 | node_modules 3 | dist 4 | .nuxt 5 | coverage 6 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "@nuxtjs/eslint-config-typescript" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | ci: 13 | runs-on: ${{ matrix.os }} 14 | 15 | strategy: 16 | matrix: 17 | # os: [ubuntu-latest, macos-latest, windows-latest] 18 | os: [ubuntu-latest] 19 | node: [12] 20 | 21 | steps: 22 | - uses: actions/setup-node@v2 23 | with: 24 | node-version: ${{ matrix.node }} 25 | 26 | - name: checkout 27 | uses: actions/checkout@v2 28 | 29 | - name: cache node_modules 30 | uses: actions/cache@v2 31 | with: 32 | path: node_modules 33 | key: ${{ matrix.os }}-node-v${{ matrix.node }}-deps-${{ hashFiles(format('{0}{1}', github.workspace, '/yarn.lock')) }} 34 | 35 | - name: Install dependencies 36 | if: steps.cache.outputs.cache-hit != 'true' 37 | run: yarn 38 | 39 | - name: Lint 40 | run: yarn lint 41 | 42 | - name: Test 43 | run: yarn test 44 | 45 | - name: Coverage 46 | uses: codecov/codecov-action@v2 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.iml 3 | .idea 4 | *.log* 5 | .nuxt 6 | .vscode 7 | .DS_Store 8 | coverage 9 | dist 10 | sw.* 11 | .env 12 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ### [1.0.1](https://github.com/nuxt-community/imagemin-module/compare/v1.0.0...v1.0.1) (2021-03-11) 6 | 7 | ## [1.0.0](https://github.com/nuxt-community/imagemin-module/compare/v0.2.0...v1.0.0) (2021-03-10) 8 | 9 | ## [0.2.0](https://github.com/nuxt-community/imagemin-module/compare/v0.1.0...v0.2.0) (2020-06-05) 10 | 11 | ## 0.1.0 (2019-12-19) 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Nuxt Community 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # @nuxtjs/imagemin 2 | 3 | [![npm version][npm-version-src]][npm-version-href] 4 | [![npm downloads][npm-downloads-src]][npm-downloads-href] 5 | [![Github Actions CI][github-actions-ci-src]][github-actions-ci-href] 6 | [![Codecov][codecov-src]][codecov-href] 7 | [![License][license-src]][license-href] 8 | 9 | > Automatically optimize (compress) all images used in Nuxt.js 10 | 11 | [📖 **Release Notes**](./CHANGELOG.md) 12 | 13 | ## Setup 14 | 15 | 1. Add `@nuxtjs/imagemin` dependency to your project 16 | 17 | ```bash 18 | yarn add --dev @nuxtjs/imagemin # or npm install --save-dev @nuxtjs/imagemin 19 | ``` 20 | 21 | 2. Add `@nuxtjs/imagemin` to the `buildModules` section of `nuxt.config.js` 22 | 23 | ```js 24 | export default { 25 | buildModules: [ 26 | // Simple usage 27 | '@nuxtjs/imagemin', 28 | 29 | // With options 30 | ['@nuxtjs/imagemin', { /* module options */ }] 31 | ] 32 | } 33 | ``` 34 | 35 | :warning: If you are using Nuxt **< v2.9** you have to install the module as a `dependency` (No `--dev` or `--save-dev` flags) and use `modules` section in `nuxt.config.js` instead of `buildModules`. 36 | 37 | ### Using top level options 38 | 39 | ```js 40 | export default { 41 | buildModules: [ 42 | '@nuxtjs/imagemin' 43 | ], 44 | imagemin: { 45 | /* module options */ 46 | } 47 | } 48 | ``` 49 | 50 | ## Options 51 | 52 | See [image-minimizer-webpack-plugin](https://github.com/webpack-contrib/image-minimizer-webpack-plugin#options) for the complete list of options available. 53 | 54 | ### `enableInDev` 55 | 56 | - Type: `Boolean` 57 | - Default: `false` 58 | 59 | Images will be minified in development mode, if this option is set to `true`. 60 | 61 | **This could increase the build time.** 62 | 63 | ## `minimizerOptions` 64 | 65 | - Type: `Object` 66 | - Default: 67 | 68 | ```js 69 | plugins: [ 70 | ['gifsicle', { interlaced: true }], 71 | ['jpegtran', { progressive: true }], 72 | ['optipng', { optimizationLevel: 5 }], 73 | ['svgo', { plugins: [{ removeViewBox: false }] }] 74 | ] 75 | ``` 76 | 77 | ## Development 78 | 79 | 1. Clone this repository 80 | 2. Install dependencies using `yarn install` or `npm install` 81 | 3. Start development server using `npm run dev` 82 | 83 | ## License 84 | 85 | [MIT License](./LICENSE) 86 | 87 | Copyright (c) Nuxt Community 88 | 89 | 90 | [npm-version-src]: https://img.shields.io/npm/v/@nuxtjs/imagemin/latest.svg 91 | [npm-version-href]: https://npmjs.com/package/@nuxtjs/imagemin 92 | 93 | [npm-downloads-src]: https://img.shields.io/npm/dt/@nuxtjs/imagemin.svg 94 | [npm-downloads-href]: https://npmjs.com/package/@nuxtjs/imagemin 95 | 96 | [github-actions-ci-src]: https://github.com/nuxt-community/imagemin-module/workflows/ci/badge.svg 97 | [github-actions-ci-href]: https://github.com/nuxt-community/imagemin-module/actions?query=workflow%3Aci 98 | 99 | [codecov-src]: https://img.shields.io/codecov/c/github/nuxt-community/imagemin-module.svg 100 | [codecov-href]: https://codecov.io/gh/nuxt-community/imagemin-module 101 | 102 | [license-src]: https://img.shields.io/npm/l/@nuxtjs/imagemin.svg 103 | [license-href]: https://npmjs.com/package/@nuxtjs/imagemin 104 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: '@nuxt/test-utils', 3 | collectCoverageFrom: ['src/**'] 4 | } 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@nuxtjs/imagemin", 3 | "version": "1.0.1", 4 | "description": "Automatically optimize (compress) all images used in Nuxt.js", 5 | "repository": "nuxt-community/imagemin-module", 6 | "license": "MIT", 7 | "contributors": [ 8 | "Ricardo Gobbo de Souza " 9 | ], 10 | "main": "./dist/module.js", 11 | "types": "./dist/module.d.ts", 12 | "files": [ 13 | "dist" 14 | ], 15 | "scripts": { 16 | "build": "siroc build", 17 | "prepublishOnly": "yarn build", 18 | "dev": "nuxt dev test/fixture", 19 | "lint": "eslint --ext .js,.ts,.vue .", 20 | "release": "yarn test && yarn build && standard-version && git push --follow-tags && npm publish", 21 | "test": "yarn lint && yarn jest" 22 | }, 23 | "dependencies": { 24 | "consola": "^2.15.3", 25 | "image-minimizer-webpack-plugin": "^1.0.0", 26 | "imagemin-gifsicle": "^7.0.0", 27 | "imagemin-jpegtran": "^7.0.0", 28 | "imagemin-mozjpeg": "^9.0.0", 29 | "imagemin-optipng": "^8.0.0", 30 | "imagemin-pngquant": "^9.0.2", 31 | "imagemin-svgo": "^9.0.0" 32 | }, 33 | "devDependencies": { 34 | "@babel/preset-typescript": "latest", 35 | "@nuxt/test-utils": "latest", 36 | "@nuxt/types": "latest", 37 | "@nuxtjs/eslint-config-typescript": "latest", 38 | "@types/jest": "latest", 39 | "@types/node": "latest", 40 | "del": "latest", 41 | "eslint": "latest", 42 | "fs-extra": "latest", 43 | "glob": "latest", 44 | "jest": "latest", 45 | "nuxt": "latest", 46 | "siroc": "latest", 47 | "standard-version": "latest" 48 | }, 49 | "publishConfig": { 50 | "access": "public" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "@nuxtjs" 4 | ], 5 | "ignoreDeps": [ 6 | "image-minimizer-webpack-plugin" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /src/module.ts: -------------------------------------------------------------------------------- 1 | import type { Module } from '@nuxt/types' 2 | import consola from 'consola' 3 | import defu from 'defu' 4 | import { name, version } from '../package.json' 5 | 6 | const logger = consola.withTag('nuxt:imagemin') 7 | 8 | // TODO: remove when nuxtjs support webpack 5 9 | // using PluginOptions from image-minimizer-webpack-plugin 10 | // https://github.com/webpack-contrib/image-minimizer-webpack-plugin/releases/tag/v2.0.0 11 | interface PluginOptions { 12 | test?: string | RegExp | string[] | RegExp[]; 13 | include?: string | RegExp | string[] | RegExp[]; 14 | exclude?: string | RegExp | string[] | RegExp[]; 15 | filter?: Function; 16 | cache?: boolean; 17 | severityError?: boolean | string; 18 | minimizerOptions: object; 19 | loader?: boolean; 20 | maxConcurrency?: number; 21 | filename?: string; 22 | deleteOriginalAssets?: boolean; 23 | } 24 | 25 | export interface ModuleOptions extends PluginOptions { 26 | enableInDev: boolean; 27 | } 28 | 29 | const CONFIG_KEY = 'imagemin' 30 | 31 | const nuxtModule: Module = function (moduleOptions) { 32 | const DEFAULTS: ModuleOptions = { 33 | enableInDev: false, 34 | minimizerOptions: { 35 | plugins: [ 36 | ['gifsicle', { interlaced: true }], 37 | ['jpegtran', { progressive: true }], 38 | ['optipng', { optimizationLevel: 5 }], 39 | ['svgo', { plugins: [{ removeViewBox: false }] }] 40 | ] 41 | } 42 | } 43 | 44 | const options: ModuleOptions = defu( 45 | this.options[CONFIG_KEY], 46 | moduleOptions, 47 | DEFAULTS 48 | ) 49 | 50 | if (this.options.dev) { 51 | if (!options.enableInDev) { 52 | return 53 | } 54 | 55 | logger.warn('Imagemin is activated in development mode. This could increase the build time.') 56 | } 57 | 58 | this.extendBuild((config) => { 59 | const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin') 60 | 61 | delete options.enableInDev 62 | 63 | config.plugins.push(new ImageMinimizerPlugin(options)) 64 | }) 65 | } 66 | 67 | ;(nuxtModule as any).meta = { name, version } 68 | 69 | declare module '@nuxt/types' { 70 | interface NuxtConfig { [CONFIG_KEY]?: ModuleOptions } // Nuxt 2.14+ 71 | interface Configuration { [CONFIG_KEY]?: ModuleOptions } // Nuxt 2.9 - 2.13 72 | } 73 | 74 | export default nuxtModule 75 | -------------------------------------------------------------------------------- /test/dev.test.ts: -------------------------------------------------------------------------------- 1 | import { setupTest, get } from '@nuxt/test-utils' 2 | 3 | describe('dev', () => { 4 | setupTest({ 5 | server: true, 6 | config: { 7 | dev: true 8 | } 9 | }) 10 | 11 | test('render', async () => { 12 | const { body } = await get('/') 13 | expect(body).toContain('Works!') 14 | }) 15 | }) 16 | -------------------------------------------------------------------------------- /test/fixture/assets/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuxt-community/imagemin-module/5af2868e716156caeb65e5e24f0dca4c16d9ba3a/test/fixture/assets/example.png -------------------------------------------------------------------------------- /test/fixture/nuxt.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | rootDir: __dirname, 3 | buildModules: [ 4 | '../../src/module.ts' 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /test/fixture/pages/index.vue: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /test/prod.test.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from 'path' 2 | import { statSync } from 'fs-extra' 3 | import { setupTest, getNuxt } from '@nuxt/test-utils' 4 | import { sync as globSync } from 'glob' 5 | 6 | describe('prod', () => { 7 | setupTest({ 8 | build: true, 9 | config: { 10 | dev: false 11 | } 12 | }) 13 | 14 | test('image minify', () => { 15 | const { options } = getNuxt() 16 | const originalFileSize = statSync(resolve(options.rootDir, options.dir.assets, 'example.png')).size 17 | const mapFiles = globSync(resolve(options.buildDir, 'dist/client/**/*.png')) 18 | const minFileSize = statSync(mapFiles[0]).size 19 | 20 | expect(originalFileSize).toBeGreaterThan(minFileSize) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /test/warn.test.ts: -------------------------------------------------------------------------------- 1 | import { setupTest, mockConsola } from '@nuxt/test-utils' 2 | 3 | const logger = mockConsola() 4 | 5 | describe('warn', () => { 6 | setupTest({ 7 | config: { 8 | dev: true, 9 | imagemin: { 10 | enableInDev: true 11 | } 12 | } 13 | }) 14 | 15 | test('should warn if enabled in dev mode', () => { 16 | expect(logger.warn).toHaveBeenCalledWith( 17 | 'Imagemin is activated in development mode. This could increase the build time.' 18 | ) 19 | }) 20 | }) 21 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "resolveJsonModule": true, 7 | "strict": false, 8 | "types": [ 9 | "node", 10 | "jest" 11 | ] 12 | }, 13 | "exclude": [ 14 | "node_modules", 15 | "dist" 16 | ] 17 | } 18 | --------------------------------------------------------------------------------