├── .eslintignore
├── .eslintrc
├── jest.config.js
├── test
├── fixture
│ ├── assets
│ │ └── example.png
│ ├── nuxt.config.js
│ └── pages
│ │ └── index.vue
├── dev.test.ts
├── warn.test.ts
└── prod.test.ts
├── renovate.json
├── .gitignore
├── .editorconfig
├── tsconfig.json
├── CHANGELOG.md
├── LICENSE
├── .github
└── workflows
│ └── ci.yml
├── package.json
├── src
└── module.ts
└── README.md
/.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 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: '@nuxt/test-utils',
3 | collectCoverageFrom: ['src/**']
4 | }
5 |
--------------------------------------------------------------------------------
/test/fixture/assets/example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nuxt-community/imagemin-module/main/test/fixture/assets/example.png
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "@nuxtjs"
4 | ],
5 | "ignoreDeps": [
6 | "image-minimizer-webpack-plugin"
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/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 |
2 |
3 | Works!
4 |

5 |
6 |
7 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------